diff --git a/.gitignore b/.gitignore index 1768ebb161f..dc932d1f5c1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,11 @@ .vs/* !.vs/VSWorkspaceSettings.json +# Byte-compiled python files +*.pyc + # It's useful (though not required) to be able to unpack codeql in the ql checkout itself /codeql/ -.vscode/settings.json + csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json +.vscode diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index af8575bc316..9853e6b91b8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to CodeQL -We welcome contributions to our CodeQL libraries and queries. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! +We welcome contributions to our CodeQL libraries and queries. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE). There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). @@ -47,10 +47,6 @@ If you have an idea for a query that you would like to share with other CodeQL u - The query must have at least one true positive result on some revision of a real project. -6. **Contributor License Agreement** - - - The contributor can satisfy the [CLA](#contributor-license-agreement). - Experimental queries and libraries may not be actively maintained as the [supported](docs/supported-queries.md) libraries evolve. They may also be changed in backwards-incompatible ways or may be removed entirely in the future without deprecation warnings. After the experimental query is merged, we welcome pull requests to improve it. Before a query can be moved out of the `experimental` subdirectory, it must satisfy [the requirements for being a supported query](docs/supported-queries.md). @@ -65,33 +61,6 @@ normal course of software development. We also store records of your CLA agreements. Under GDPR legislation, we do this on the basis of our legitimate interest in creating the CodeQL product. -Please do get in touch (privacy@semmle.com) if you have any questions about +Please do get in touch (privacy@github.com) if you have any questions about this or our data protection policies. -## Contributor License Agreement - -This Contributor License Agreement (“Agreement”) is entered into between Semmle Limited (“Semmle,” “we” or “us” etc.), and You (as defined and further identified below). - -Accordingly, You hereby agree to the following terms for Your present and future Contributions submitted to Semmle: - -1. **Definitions**. - - * "You" (or "Your") shall mean the Contribution copyright owner (whether an individual or organization) or legal entity authorized by the copyright owner that is making this Agreement with Semmle. For legal entities, the entity making a Contribution and all other entities that control, are controlled by, or are under common control with that entity are considered to be a single Contributor. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - * "Contribution(s)" shall mean the code, documentation or other original works of authorship, including any modifications or additions to an existing work, submitted by You to Semmle for inclusion in, or documentation of, any of the products or projects owned or managed by Semmle (the "Work(s)"). For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to Semmle or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, Semmle for the purpose of discussing and/or improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by You as "Not a Contribution." - -2. **Grant of Copyright License**. You hereby grant to Semmle and to recipients of software distributed by Semmle a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your Contributions and such derivative works. - -3. **Grant of Patent License**. You hereby grant to Semmle and to recipients of software distributed by Semmle a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution(s) alone or by combination of Your Contribution(s) with the Work to which such Contribution(s) was submitted. If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that Your Contribution, or the Work to which You have contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution or Work shall terminate as of the date such litigation is filed. - -4. **Ownership**. Except as set out above, You keep all right, title, and interest in Your Contribution. The rights that You grant to us under this Agreement are effective on the date You first submitted a Contribution to us, even if Your submission took place before the date You entered this Agreement. - -5. **Representations**. You represent and warrant that: (i) the Contributions are an original work and that You can legally grant the rights set out in this Agreement; (ii) the Contributions and Semmle’s exercise of any license rights granted hereunder, does not and will not, infringe the rights of any third party; (iii) You are not aware of any pending or threatened claims, suits, actions, or charges pertaining to the Contributions, including without limitation any claims or allegations that any or all of the Contributions infringes, violates, or misappropriate the intellectual property rights of any third party (You further agree that You will notify Semmle immediately if You become aware of any such actual or potential claims, suits, actions, allegations or charges). - -6. **Employer**. If Your employer(s) has rights to intellectual property that You create that includes Your Contributions, You represent and warrant that Your employer has waived such rights for Your Contributions to Semmle, or that You have received permission to make Contributions on behalf of that employer and that You are authorized to execute this Agreement on behalf of Your employer. - -7. **Inclusion of Code**. We determine the code that is in our Works. You understand that the decision to include the Contribution in any project or source repository is entirely that of Semmle, and this agreement does not guarantee that the Contributions will be included in any product. - -8. **Disclaimer**. You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. You may provide support for free, for a fee, or not at all. Except as set forth herein, and unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. - -9. **General**. The failure of either party to enforce its rights under this Agreement for any period shall not be construed as a waiver of such rights. No changes or modifications or waivers to this Agreement will be effective unless in writing and signed by both parties. In the event that any provision of this Agreement shall be determined to be illegal or unenforceable, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement shall otherwise remain in full force and effect and enforceable. This Agreement shall be governed by and construed in accordance with the laws of the State of California in the United States without regard to the conflicts of laws provisions thereof. In any action or proceeding to enforce rights under this Agreement, the prevailing party will be entitled to recover costs and attorneys’ fees. diff --git a/COPYRIGHT b/COPYRIGHT deleted file mode 100644 index 65d947ff274..00000000000 --- a/COPYRIGHT +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) Semmle Inc and other contributors. All rights reserved. - -Licensed 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 - -THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED -WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, -MERCHANTABLITY OR NON-INFRINGEMENT. - -See the Apache Version 2.0 License for specific language governing permissions -and limitations under the License. diff --git a/LICENSE b/LICENSE index d9a10c0d8e8..e29b05cd648 100644 --- a/LICENSE +++ b/LICENSE @@ -1,176 +1,21 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +MIT License - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Copyright (c) 2006-2020 GitHub, Inc. - 1. Definitions. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 1f77856cfc4..7d2fb59bf1a 100644 --- a/README.md +++ b/README.md @@ -13,4 +13,4 @@ We welcome contributions to our standard library and standard checks. Do you hav ## License -The code in this repository is licensed under [Apache License 2.0](LICENSE) by [GitHub](https://github.com). +The code in this repository is licensed under the [MIT License](LICENSE) by [GitHub](https://github.com). diff --git a/change-notes/1.24/analysis-cpp.md b/change-notes/1.24/analysis-cpp.md index 75e37d43ead..8f8c3d5364a 100644 --- a/change-notes/1.24/analysis-cpp.md +++ b/change-notes/1.24/analysis-cpp.md @@ -20,9 +20,12 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. | Memory may not be freed (`cpp/memory-may-not-be-freed`) | More true positive results | This query now identifies a wider variety of buffer allocations using the `semmle.code.cpp.models.interfaces.Allocation` library. | | Mismatching new/free or malloc/delete (`cpp/new-free-mismatch`) | Fewer false positive results | Fixed false positive results in template code. | | Missing return statement (`cpp/missing-return`) | Fewer false positive results | Functions containing `asm` statements are no longer highlighted by this query. | +| Missing return statement (`cpp/missing-return`) | More accurate locations | Locations reported by this query are now more accurate in some cases. | | No space for zero terminator (`cpp/no-space-for-terminator`) | More correct results | String arguments to formatting functions are now (usually) expected to be null terminated strings. | | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. | | No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. | +| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | Cases where the tainted allocation size is range checked are now more reliably excluded. | +| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | The query now produces fewer, more accurate results. | | Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. | | Unsafe array for days of the year (`cpp/leap-year/unsafe-array-for-days-of-the-year`) | | This query is no longer run on LGTM. | | Unsigned comparison to zero (`cpp/unsigned-comparison-zero`) | More correct results | This query now also looks for comparisons of the form `0 <= x`. | @@ -45,9 +48,11 @@ The following changes in version 1.24 affect C/C++ analysis in all applications. `StackVariableReachability`. The functionality is the same. * The models library models `strlen` in more detail, and includes common variations such as `wcslen`. * The models library models `gets` and similar functions. +* The models library now partially models `std::string`. * The taint tracking library (`semmle.code.cpp.dataflow.TaintTracking`) has had the following improvements: * The library now models data flow through `strdup` and similar functions. * The library now models data flow through formatting functions such as `sprintf`. * The security pack taint tracking library (`semmle.code.cpp.security.TaintTracking`) uses a new intermediate representation. This provides a more precise analysis of pointers to stack variables and flow through parameters, improving the results of many security queries. * The global value numbering library (`semmle.code.cpp.valuenumbering.GlobalValueNumbering`) uses a new intermediate representation to provide a more precise analysis of heap allocated memory and pointers to stack variables. +* `freeCall` in `semmle.code.cpp.commons.Alloc` has been deprecated. The`Allocation` and `Deallocation` models in `semmle.code.cpp.models.interfaces` should be used instead. diff --git a/change-notes/1.24/analysis-csharp.md b/change-notes/1.24/analysis-csharp.md index 02f31b12533..a745e985eae 100644 --- a/change-notes/1.24/analysis-csharp.md +++ b/change-notes/1.24/analysis-csharp.md @@ -22,6 +22,8 @@ The following changes in version 1.24 affect C# analysis in all applications. | Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | More results | Results are reported from parameters with a default value of `null`. | | Useless assignment to local variable (`cs/useless-assignment-to-local`) | Fewer false positive results | Results have been removed when the value assigned is an (implicitly or explicitly) cast default-like value. For example, `var s = (string)null` and `string s = default`. | | XPath injection (`cs/xml/xpath-injection`) | More results | The query now recognizes calls to methods on `System.Xml.XPath.XPathNavigator` objects. | +| Information exposure through transmitted data (`cs/sensitive-data-transmission`) | More results | The query now recognizes writes to cookies and writes to ASP.NET (`Inner`)`Text` properties as additional sinks. | +| Information exposure through an exception (`cs/information-exposure-through-exception`) | More results | The query now recognizes writes to cookies, writes to ASP.NET (`Inner`)`Text` properties, and email contents as additional sinks. | ## Removal of old queries @@ -42,5 +44,6 @@ The following changes in version 1.24 affect C# analysis in all applications. * [Code contracts](https://docs.microsoft.com/en-us/dotnet/framework/debug-trace-profile/code-contracts) are now recognized, and are treated like any other assertion methods. * Expression nullability flow state is given by the predicates `Expr.hasNotNullFlowState()` and `Expr.hasMaybeNullFlowState()`. * `stackalloc` array creations are now represented by the QL class `Stackalloc`. Previously they were represented by the class `ArrayCreation`. +* A new class `RemoteFlowSink` has been added to model sinks where data might be exposed to external users. Examples include web page output, e-mails, and cookies. ## Changes to autobuilder diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 7c72ecea6b1..c27f7850041 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -86,6 +86,7 @@ | Useless regular-expression character escape (`js/useless-regexp-character-escape`) | Fewer false positive results | This query now distinguishes escapes in strings and regular expression literals. | | Identical operands (`js/redundant-operation`) | Fewer results | This query now recognizes cases where the operands change a value using ++/-- expressions. | | Superfluous trailing arguments (`js/superfluous-trailing-arguments`) | Fewer results | This query now recognizes cases where a function uses the `Function.arguments` value to process a variable number of parameters. | +| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional variations of URL scheme checks. | ## Changes to libraries diff --git a/change-notes/1.25/analysis-javascript.md b/change-notes/1.25/analysis-javascript.md new file mode 100644 index 00000000000..a49aa9230b1 --- /dev/null +++ b/change-notes/1.25/analysis-javascript.md @@ -0,0 +1,22 @@ +# Improvements to JavaScript analysis + +## General improvements + + +## New queries + +| **Query** | **Tags** | **Purpose** | +|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| + + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. | +| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. | +| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. | + +## Changes to libraries + + diff --git a/config/identical-files.json b/config/identical-files.json index 47b37455b8c..a5af067ab5d 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -39,6 +39,12 @@ "java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll" ], + "DataFlow Java/C++/C# Consistency checks": [ + "java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", + "cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", + "cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", + "csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll" + ], "C++ SubBasicBlocks": [ "cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll", "cpp/ql/src/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll" @@ -236,6 +242,13 @@ "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll", "csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll" ], + "C++ IR PrintValueNumbering": [ + "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll", + "cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll", + "csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll" + ], "C++ IR ConstantAnalysis": [ "cpp/ql/src/semmle/code/cpp/ir/implementation/raw/constant/ConstantAnalysis.qll", "cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/constant/ConstantAnalysis.qll", diff --git a/config/sync-files.py b/config/sync-files.py new file mode 100644 index 00000000000..30be173c18b --- /dev/null +++ b/config/sync-files.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +# Due to various technical limitations, we sometimes have files that need to be +# kept identical in the repository. This script loads a database of such +# files and can perform two functions: check whether they are still identical, +# and overwrite the others with a master copy if needed. + +import hashlib +import shutil +import os +import sys +import json +import re +path = os.path + +file_groups = {} + +def add_prefix(prefix, relative): + result = path.join(prefix, relative) + if path.commonprefix((path.realpath(result), path.realpath(prefix))) != \ + path.realpath(prefix): + raise Exception("Path {} is not below {}".format( + result, prefix)) + return result + +def load_if_exists(prefix, json_file_relative): + json_file_name = path.join(prefix, json_file_relative) + if path.isfile(json_file_name): + print("Loading file groups from", json_file_name) + with open(json_file_name, 'r', encoding='utf-8') as fp: + raw_groups = json.load(fp) + prefixed_groups = { + name: [ + add_prefix(prefix, relative) + for relative in relatives + ] + for name, relatives in raw_groups.items() + } + file_groups.update(prefixed_groups) + +# Generates a list of C# test files that should be in sync +def csharp_test_files(): + test_file_re = re.compile('.*(Bad|Good)[0-9]*\\.cs$') + csharp_doc_files = { + file:os.path.join(root, file) + for root, dirs, files in os.walk("csharp/ql/src") + for file in files + if test_file_re.match(file) + } + return { + "C# test '" + file + "'" : [os.path.join(root, file), csharp_doc_files[file]] + for root, dirs, files in os.walk("csharp/ql/test") + for file in files + if file in csharp_doc_files + } + +def file_checksum(filename): + with open(filename, 'rb') as file_handle: + return hashlib.sha1(file_handle.read()).hexdigest() + +def check_group(group_name, files, master_file_picker, emit_error): + checksums = {file_checksum(f) for f in files} + + if len(checksums) == 1: + return + + master_file = master_file_picker(files) + if master_file is None: + emit_error(__file__, 0, + "Files from group '"+ group_name +"' not in sync.") + emit_error(__file__, 0, + "Run this script with a file-name argument among the " + "following to overwrite the remaining files with the contents " + "of that file or run with the --latest switch to update each " + "group of files from the most recently modified file in the group.") + for filename in files: + emit_error(__file__, 0, " " + filename) + else: + print(" Syncing others from", master_file) + for filename in files: + if filename == master_file: + continue + print(" " + filename) + os.replace(filename, filename + '~') + shutil.copy(master_file, filename) + print(" Backups written with '~' appended to file names") + +def chdir_repo_root(): + root_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..') + os.chdir(root_path) + +def choose_master_file(master_file, files): + if master_file in files: + return master_file + else: + return None + +def choose_latest_file(files): + latest_time = None + latest_file = None + for filename in files: + file_time = os.path.getmtime(filename) + if (latest_time is None) or (latest_time < file_time): + latest_time = file_time + latest_file = filename + return latest_file + +local_error_count = 0 +def emit_local_error(path, line, error): + print('ERROR: ' + path + ':' + line + " - " + error) + global local_error_count + local_error_count += 1 + +# This function is invoked directly by a CI script, which passes a different error-handling +# callback. +def sync_identical_files(emit_error): + if len(sys.argv) == 1: + master_file_picker = lambda files: None + elif len(sys.argv) == 2: + if sys.argv[1] == "--latest": + master_file_picker = choose_latest_file + elif os.path.isfile(sys.argv[1]): + master_file_picker = lambda files: choose_master_file(sys.argv[1], files) + else: + raise Exception("File not found") + else: + raise Exception("Bad command line or file not found") + chdir_repo_root() + load_if_exists('.', 'config/identical-files.json') + file_groups.update(csharp_test_files()) + for group_name, files in file_groups.items(): + check_group(group_name, files, master_file_picker, emit_error) + +def main(): + sync_identical_files(emit_local_error) + if local_error_count > 0: + exit(1) + +if __name__ == "__main__": + main() diff --git a/cpp/ql/src/Critical/FileClosed.qll b/cpp/ql/src/Critical/FileClosed.qll index 1e782259156..e2ba3c25b81 100644 --- a/cpp/ql/src/Critical/FileClosed.qll +++ b/cpp/ql/src/Critical/FileClosed.qll @@ -1,5 +1,6 @@ import semmle.code.cpp.pointsto.PointsTo +/** Holds if there exists a call to a function that might close the file specified by `e`. */ predicate closed(Expr e) { fcloseCall(_, e) or exists(ExprCall c | @@ -8,10 +9,19 @@ predicate closed(Expr e) { ) } +/** An expression for which there exists a function call that might close it. */ class ClosedExpr extends PointsToExpr { ClosedExpr() { closed(this) } override predicate interesting() { closed(this) } } +/** + * Holds if `fc` is a call to a function that opens a file that might be closed. For example: + * ``` + * FILE* f = fopen("file.txt", "r"); + * ... + * fclose(f); + * ``` + */ predicate fopenCallMayBeClosed(FunctionCall fc) { fopenCall(fc) and anythingPointsTo(fc) } diff --git a/cpp/ql/src/Critical/LoopBounds.qll b/cpp/ql/src/Critical/LoopBounds.qll index f10e62c909f..b2cde8d6fe8 100644 --- a/cpp/ql/src/Critical/LoopBounds.qll +++ b/cpp/ql/src/Critical/LoopBounds.qll @@ -2,12 +2,24 @@ import cpp +/** + * An assignment to a variable with the value `0`. For example: + * ``` + * int x; + * x = 0; + * ``` + * but not: + * ``` + * int x = 0; + * ``` + */ class ZeroAssignment extends AssignExpr { ZeroAssignment() { this.getAnOperand() instanceof VariableAccess and this.getAnOperand() instanceof Zero } + /** Gets a variable that is assigned the value `0`. */ Variable assignedVariable() { result.getAnAccess() = this.getAnOperand() } } diff --git a/cpp/ql/src/Critical/MemoryFreed.qll b/cpp/ql/src/Critical/MemoryFreed.qll index d548aca26e7..44557503e43 100644 --- a/cpp/ql/src/Critical/MemoryFreed.qll +++ b/cpp/ql/src/Critical/MemoryFreed.qll @@ -4,15 +4,24 @@ private predicate freed(Expr e) { e = any(DeallocationExpr de).getFreedExpr() or exists(ExprCall c | - // cautiously assume that any ExprCall could be a freeCall. + // cautiously assume that any `ExprCall` could be a deallocation expression. c.getAnArgument() = e ) } +/** An expression that might be deallocated. */ class FreedExpr extends PointsToExpr { FreedExpr() { freed(this) } override predicate interesting() { freed(this) } } +/** + * An allocation expression that might be deallocated. For example: + * ``` + * int* p = new int; + * ... + * delete p; + * ``` + */ predicate allocMayBeFreed(AllocationExpr alloc) { anythingPointsTo(alloc) } diff --git a/cpp/ql/src/Critical/Negativity.qll b/cpp/ql/src/Critical/Negativity.qll index 161fe234967..e9c0a3d2410 100644 --- a/cpp/ql/src/Critical/Negativity.qll +++ b/cpp/ql/src/Critical/Negativity.qll @@ -1,10 +1,19 @@ import cpp +/** + * Holds if `val` is an access to the variable `v`, or if `val` + * is an assignment with an access to `v` on the left-hand side. + */ predicate valueOfVar(Variable v, Expr val) { val = v.getAnAccess() or val.(AssignExpr).getLValue() = v.getAnAccess() } +/** + * Holds if either: + * - `cond` is an (in)equality expression that compares the variable `v` to the value `-1`, or + * - `cond` is a relational expression that compares the variable `v` to a constant. + */ predicate boundsCheckExpr(Variable v, Expr cond) { exists(EQExpr eq | cond = eq and @@ -43,6 +52,18 @@ predicate boundsCheckExpr(Variable v, Expr cond) { ) } +/** + * Holds if `node` is an expression in a conditional statement and `succ` is an + * immediate successor of `node` that may be reached after evaluating `node`. + * For example, given + * ``` + * if (a < 10 && b) func1(); + * else func2(); + * ``` + * this predicate holds when either: + * - `node` is `a < 10` and `succ` is `func2()` or `b`, or + * - `node` is `b` and `succ` is `func1()` or `func2()` + */ predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) { if node.isCondition() then succ = node.getATrueSuccessor() or succ = node.getAFalseSuccessor() @@ -52,6 +73,12 @@ predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) { ) } +/** + * Holds if the current value of the variable `v` at control-flow + * node `n` has been used either in: + * - an (in)equality comparison with the value `-1`, or + * - a relational comparison that compares `v` to a constant. + */ predicate boundsChecked(Variable v, ControlFlowNode node) { exists(Expr test | boundsCheckExpr(v, test) and @@ -63,6 +90,14 @@ predicate boundsChecked(Variable v, ControlFlowNode node) { ) } +/** + * Holds if `cond` compares `v` to some common error values. Specifically, this + * predicate holds when: + * - `cond` checks that `v` is equal to `-1`, or + * - `cond` checks that `v` is less than `0`, or + * - `cond` checks that `v` is less than or equal to `-1`, or + * - `cond` checks that `v` is not some common success value (see `successCondition`). + */ predicate errorCondition(Variable v, Expr cond) { exists(EQExpr eq | cond = eq and @@ -88,6 +123,14 @@ predicate errorCondition(Variable v, Expr cond) { ) } +/** + * Holds if `cond` compares `v` to some common success values. Specifically, this + * predicate holds when: + * - `cond` checks that `v` is not equal to `-1`, or + * - `cond` checks that `v` is greater than or equal than `0`, or + * - `cond` checks that `v` is greater than `-1`, or + * - `cond` checks that `v` is not some common error value (see `errorCondition`). + */ predicate successCondition(Variable v, Expr cond) { exists(NEExpr ne | cond = ne and @@ -113,6 +156,11 @@ predicate successCondition(Variable v, Expr cond) { ) } +/** + * Holds if there exists a comparison operation that checks whether `v` + * represents some common *error* values, and `n` may be reached + * immediately following the comparison operation. + */ predicate errorSuccessor(Variable v, ControlFlowNode n) { exists(Expr cond | errorCondition(v, cond) and n = cond.getATrueSuccessor() @@ -121,6 +169,11 @@ predicate errorSuccessor(Variable v, ControlFlowNode n) { ) } +/** + * Holds if there exists a comparison operation that checks whether `v` + * represents some common *success* values, and `n` may be reached + * immediately following the comparison operation. + */ predicate successSuccessor(Variable v, ControlFlowNode n) { exists(Expr cond | successCondition(v, cond) and n = cond.getATrueSuccessor() @@ -129,6 +182,10 @@ predicate successSuccessor(Variable v, ControlFlowNode n) { ) } +/** + * Holds if the current value of the variable `v` at control-flow node + * `n` may have been checked against a common set of *error* values. + */ predicate checkedError(Variable v, ControlFlowNode n) { errorSuccessor(v, n) or @@ -139,6 +196,10 @@ predicate checkedError(Variable v, ControlFlowNode n) { ) } +/** + * Holds if the current value of the variable `v` at control-flow node + * `n` may have been checked against a common set of *success* values. + */ predicate checkedSuccess(Variable v, ControlFlowNode n) { successSuccessor(v, n) or diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index 9dd55525b59..30b9f9ad94a 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -5,17 +5,34 @@ import cpp import semmle.code.cpp.controlflow.SSA import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.models.implementations.Allocation +import semmle.code.cpp.models.implementations.Deallocation /** * Holds if `alloc` is a use of `malloc` or `new`. `kind` is * a string describing the type of the allocation. */ predicate allocExpr(Expr alloc, string kind) { - isAllocationExpr(alloc) and - not alloc.isFromUninstantiatedTemplate(_) and ( - alloc instanceof FunctionCall and - kind = "malloc" + exists(Function target | + alloc.(AllocationExpr).(FunctionCall).getTarget() = target and + ( + target.getName() = "operator new" and + kind = "new" and + // exclude placement new and custom overloads as they + // may not conform to assumptions + not target.getNumberOfParameters() > 1 + or + target.getName() = "operator new[]" and + kind = "new[]" and + // exclude placement new and custom overloads as they + // may not conform to assumptions + not target.getNumberOfParameters() > 1 + or + not target instanceof OperatorNewAllocationFunction and + kind = "malloc" + ) + ) or alloc instanceof NewExpr and kind = "new" and @@ -28,7 +45,8 @@ predicate allocExpr(Expr alloc, string kind) { // exclude placement new and custom overloads as they // may not conform to assumptions not alloc.(NewArrayExpr).getAllocatorCall().getTarget().getNumberOfParameters() > 1 - ) + ) and + not alloc.isFromUninstantiatedTemplate(_) } /** @@ -110,8 +128,20 @@ predicate allocReaches(Expr e, Expr alloc, string kind) { * describing the type of that free or delete. */ predicate freeExpr(Expr free, Expr freed, string kind) { - freeCall(free, freed) and - kind = "free" + exists(Function target | + freed = free.(DeallocationExpr).getFreedExpr() and + free.(FunctionCall).getTarget() = target and + ( + target.getName() = "operator delete" and + kind = "delete" + or + target.getName() = "operator delete[]" and + kind = "delete[]" + or + not target instanceof OperatorDeleteDeallocationFunction and + kind = "free" + ) + ) or free.(DeleteExpr).getExpr() = freed and kind = "delete" diff --git a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql index 72852f0b86c..965bb8440b0 100644 --- a/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql +++ b/cpp/ql/src/JPL_C/LOC-3/Rule 17/BasicIntTypes.ql @@ -30,7 +30,7 @@ predicate allowedTypedefs(TypedefType t) { * Gets a type which appears literally in the declaration of `d`. */ Type getAnImmediateUsedType(Declaration d) { - d.isDefined() and + d.hasDefinition() and ( result = d.(Function).getType() or result = d.(Variable).getType() diff --git a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql index fb7edce038c..04b3d13a3f7 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql @@ -3,7 +3,7 @@ * @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols. * @kind problem * @problem.severity error - * @id cpp/boost/tls_settings_misconfiguration + * @id cpp/boost/tls-settings-misconfiguration * @tags security */ diff --git a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp index cc6b6da3abb..ad3d7d3c9e1 100644 --- a/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp +++ b/cpp/ql/src/Likely Bugs/ReturnConstTypeMember.cpp @@ -8,6 +8,6 @@ struct S { // Whereas here it does make a semantic difference. auto getValCorrect() const -> int { - return val + return val; } }; diff --git a/cpp/ql/src/Options.qll b/cpp/ql/src/Options.qll index 353d012e339..3c7e320dff6 100644 --- a/cpp/ql/src/Options.qll +++ b/cpp/ql/src/Options.qll @@ -4,7 +4,7 @@ * * By default they fall back to the reasonable defaults provided in * `DefaultOptions.qll`, but by modifying this file, you can customize - * the standard Semmle analyses to give better results for your project. + * the standard analyses to give better results for your project. */ import cpp diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 42a29b96268..496b957cca3 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -2,7 +2,7 @@ * @name Uncontrolled data used in path expression * @description Accessing paths influenced by users can allow an * attacker to access unexpected resources. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/path-injection @@ -17,6 +17,7 @@ import cpp import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /** * A function for opening a file. @@ -51,12 +52,19 @@ class FileFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { arg = 0 } } +class TaintedPathConfiguration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(FileFunction fileFunction | fileFunction.outermostWrapperFunctionCall(tainted, _)) + } +} + from - FileFunction fileFunction, Expr taintedArg, Expr taintSource, string taintCause, string callChain + FileFunction fileFunction, Expr taintedArg, Expr taintSource, PathNode sourceNode, + PathNode sinkNode, string taintCause, string callChain where fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) -select taintedArg, +select taintedArg, sourceNode, sinkNode, "This argument to a file access function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index 8b7fb83df81..0e0c4add7f6 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -2,7 +2,7 @@ * @name CGI script vulnerable to cross-site scripting * @description Writing user input directly to a web page * allows for a cross-site scripting vulnerability. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/cgi-xss @@ -13,6 +13,7 @@ import cpp import semmle.code.cpp.commons.Environment import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /** A call that prints its arguments to `stdout`. */ class PrintStdoutCall extends FunctionCall { @@ -27,8 +28,13 @@ class QueryString extends EnvironmentRead { QueryString() { getEnvironmentVariable() = "QUERY_STRING" } } -from QueryString query, PrintStdoutCall call, Element printedArg -where - call.getAnArgument() = printedArg and - tainted(query, printedArg) -select printedArg, "Cross-site scripting vulnerability due to $@.", query, "this query data" +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintStdoutCall call | call.getAnArgument() = tainted) + } +} + +from QueryString query, Element printedArg, PathNode sourceNode, PathNode sinkNode +where taintedWithPath(query, printedArg, sourceNode, sinkNode) +select printedArg, sourceNode, sinkNode, "Cross-site scripting vulnerability due to $@.", query, + "this query data" diff --git a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql index 3f234dd0678..de786d22f30 100644 --- a/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-089/SqlTainted.ql @@ -3,7 +3,7 @@ * @description Including user-supplied data in a SQL query without * neutralizing special elements can make code vulnerable * to SQL Injection. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/sql-injection @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking +import TaintedWithPath class SQLLikeFunction extends FunctionWithWrappers { SQLLikeFunction() { sqlArgument(this.getName(), _) } @@ -22,11 +23,19 @@ class SQLLikeFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { sqlArgument(this.getName(), arg) } } -from SQLLikeFunction runSql, Expr taintedArg, Expr taintSource, string taintCause, string callChain +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(SQLLikeFunction runSql | runSql.outermostWrapperFunctionCall(tainted, _)) + } +} + +from + SQLLikeFunction runSql, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, + string taintCause, string callChain where runSql.outermostWrapperFunctionCall(taintedArg, callChain) and - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) -select taintedArg, +select taintedArg, sourceNode, sinkNode, "This argument to a SQL query function is derived from $@ and then passed to " + callChain, taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql index 233fe34e6bf..943c13f9c5d 100644 --- a/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql +++ b/cpp/ql/src/Security/CWE/CWE-114/UncontrolledProcessOperation.ql @@ -3,7 +3,7 @@ * @description Using externally controlled strings in a process * operation can allow an attacker to execute malicious * commands. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/uncontrolled-process-operation @@ -14,13 +14,24 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -from string processOperation, int processOperationArg, FunctionCall call, Expr arg, Element source +predicate isProcessOperationExplanation(Expr arg, string processOperation) { + exists(int processOperationArg, FunctionCall call | + isProcessOperationArgument(processOperation, processOperationArg) and + call.getTarget().getName() = processOperation and + call.getArgument(processOperationArg) = arg + ) +} + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element arg) { isProcessOperationExplanation(arg, _) } +} + +from string processOperation, Expr arg, Expr source, PathNode sourceNode, PathNode sinkNode where - isProcessOperationArgument(processOperation, processOperationArg) and - call.getTarget().getName() = processOperation and - call.getArgument(processOperationArg) = arg and - tainted(source, arg) -select arg, + isProcessOperationExplanation(arg, processOperation) and + taintedWithPath(source, arg, sourceNode, sinkNode) +select arg, sourceNode, sinkNode, "The value of this argument may come from $@ and is being passed to " + processOperation, source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql index ff136d2c06b..f1a8b4e8544 100644 --- a/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql @@ -2,7 +2,7 @@ * @name Unbounded write * @description Buffer write operations that do not control the length * of data written may overflow. - * @kind problem + * @kind path-problem * @problem.severity error * @precision medium * @id cpp/unbounded-write @@ -16,6 +16,7 @@ import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath /* * --- Summary of CWE-120 alerts --- @@ -54,32 +55,48 @@ predicate isUnboundedWrite(BufferWrite bw) { * } */ +/** + * Holds if `e` is a source buffer going into an unbounded write `bw` or a + * qualifier of (a qualifier of ...) such a source. + */ +predicate unboundedWriteSource(Expr e, BufferWrite bw) { + isUnboundedWrite(bw) and e = bw.getASource() + or + exists(FieldAccess fa | unboundedWriteSource(fa, bw) and e = fa.getQualifier()) +} + /* * --- user input reach --- */ -/** - * Identifies expressions that are potentially tainted with user - * input. Most of the work for this is actually done by the - * TaintTracking library. - */ -predicate tainted2(Expr expr, Expr inputSource, string inputCause) { - taintedIncludingGlobalVars(inputSource, expr, _) and - inputCause = inputSource.toString() - or - exists(Expr e | tainted2(e, inputSource, inputCause) | - // field accesses of a tainted struct are tainted - e = expr.(FieldAccess).getQualifier() - ) +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { unboundedWriteSource(tainted, _) } + + override predicate taintThroughGlobals() { any() } } /* * --- put it together --- */ -from BufferWrite bw, Expr inputSource, string inputCause +/* + * An unbounded write is, for example `strcpy(..., tainted)`. We're looking + * for a tainted source buffer of an unbounded write, where this source buffer + * is a sink in the taint-tracking analysis. + * + * In the case of `gets` and `scanf`, where the source buffer is implicit, the + * `BufferWrite` library reports the source buffer to be the same as the + * destination buffer. Since those destination-buffer arguments are also + * modeled in the taint-tracking library as being _sources_ of taint, they are + * in practice reported as being tainted because the `security.TaintTracking` + * library does not distinguish between taint going into an argument and out of + * an argument. Thus, we get the desired alerts. + */ + +from BufferWrite bw, Expr inputSource, Expr tainted, PathNode sourceNode, PathNode sinkNode where - isUnboundedWrite(bw) and - tainted2(bw.getASource(), inputSource, inputCause) -select bw, "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", - inputSource, inputCause + taintedWithPath(inputSource, tainted, sourceNode, sinkNode) and + unboundedWriteSource(tainted, bw) +select bw, sourceNode, sinkNode, + "This '" + bw.getBWDesc() + "' with input from $@ may overflow the destination.", inputSource, + inputSource.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql index 02a0f42fa6b..91ccc5c4d40 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql @@ -3,7 +3,7 @@ * @description Using externally-controlled format strings in * printf-style functions can lead to buffer overflows * or data representation problems. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-format-string @@ -16,12 +16,21 @@ import cpp import semmle.code.cpp.security.Security import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -from PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _)) + } +} + +from + PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode, + string printfFunction, Expr userValue, string cause where printf.outermostWrapperFunctionCall(arg, printfFunction) and - tainted(userValue, arg) and + taintedWithPath(userValue, arg, sourceNode, sinkNode) and isUserInput(userValue, cause) -select arg, +select arg, sourceNode, sinkNode, "The value of this argument may come from $@ and is being used as a formatting argument to " + printfFunction, userValue, cause diff --git a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql index f3cb4fcf1bb..96cffdb024b 100644 --- a/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql +++ b/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql @@ -3,7 +3,7 @@ * @description Using externally-controlled format strings in * printf-style functions can lead to buffer overflows * or data representation problems. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-format-string-through-global @@ -16,15 +16,24 @@ import cpp import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { + exists(PrintfLikeFunction printf | printf.outermostWrapperFunctionCall(tainted, _)) + } + + override predicate taintThroughGlobals() { any() } +} from - PrintfLikeFunction printf, Expr arg, string printfFunction, Expr userValue, string cause, - string globalVar + PrintfLikeFunction printf, Expr arg, PathNode sourceNode, PathNode sinkNode, + string printfFunction, Expr userValue, string cause where printf.outermostWrapperFunctionCall(arg, printfFunction) and - not tainted(_, arg) and - taintedIncludingGlobalVars(userValue, arg, globalVar) and + not taintedWithoutGlobals(arg) and + taintedWithPath(userValue, arg, sourceNode, sinkNode) and isUserInput(userValue, cause) -select arg, - "This value may flow through $@, originating from $@, and is a formatting argument to " + - printfFunction + ".", globalVarFromId(globalVar), globalVar, userValue, cause +select arg, sourceNode, sinkNode, + "The value of this argument may come from $@ and is being used as a formatting argument to " + + printfFunction, userValue, cause diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 8013fbcf614..a4b0f131d14 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -2,7 +2,7 @@ * @name Uncontrolled data in arithmetic expression * @description Arithmetic operations on uncontrolled data that is not * validated can cause overflows. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/uncontrolled-arithmetic @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.TaintTracking +import TaintedWithPath predicate isRandCall(FunctionCall fc) { fc.getTarget().getName() = "rand" } @@ -40,9 +41,22 @@ class SecurityOptionsArith extends SecurityOptions { } } -predicate taintedVarAccess(Expr origin, VariableAccess va) { - isUserInput(origin, _) and - tainted(origin, va) +predicate isDiv(VariableAccess va) { exists(AssignDivExpr div | div.getLValue() = va) } + +predicate missingGuard(VariableAccess va, string effect) { + exists(Operation op | op.getAnOperand() = va | + missingGuardAgainstUnderflow(op, va) and effect = "underflow" + or + missingGuardAgainstOverflow(op, va) and effect = "overflow" + ) +} + +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element e) { + isDiv(e) + or + missingGuard(e, _) + } } /** @@ -50,19 +64,17 @@ predicate taintedVarAccess(Expr origin, VariableAccess va) { * range. */ predicate guardedByAssignDiv(Expr origin) { - isUserInput(origin, _) and - exists(AssignDivExpr div, VariableAccess va | tainted(origin, va) and div.getLValue() = va) + exists(VariableAccess va | + taintedWithPath(origin, va, _, _) and + isDiv(va) + ) } -from Expr origin, Operation op, VariableAccess va, string effect +from Expr origin, VariableAccess va, string effect, PathNode sourceNode, PathNode sinkNode where - taintedVarAccess(origin, va) and - op.getAnOperand() = va and - ( - missingGuardAgainstUnderflow(op, va) and effect = "underflow" - or - missingGuardAgainstOverflow(op, va) and effect = "overflow" - ) and + taintedWithPath(origin, va, sourceNode, sinkNode) and + missingGuard(va, effect) and not guardedByAssignDiv(origin) -select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", - origin, "Uncontrolled value" +select va, sourceNode, sinkNode, + "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin, + "Uncontrolled value" diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 85248a26d19..54c6d1e7a96 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -2,7 +2,7 @@ * @name Overflow in uncontrolled allocation size * @description Allocating memory with a size controlled by an external * user can result in integer overflow. - * @kind problem + * @kind path-problem * @problem.severity error * @precision high * @id cpp/uncontrolled-allocation-size @@ -13,21 +13,33 @@ import cpp import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -predicate taintedAllocSize(Expr e, Expr source, string taintCause) { - ( - isAllocationExpr(e) or - any(MulExpr me | me.getAChild() instanceof SizeofOperator) = e - ) and +/** + * Holds if `alloc` is an allocation, and `tainted` is a child of it that is a + * taint sink. + */ +predicate allocSink(Expr alloc, Expr tainted) { + isAllocationExpr(alloc) and + tainted = alloc.getAChild() and + tainted.getUnspecifiedType() instanceof IntegralType +} + +class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { allocSink(_, tainted) } +} + +predicate taintedAllocSize( + Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause +) { + isUserInput(source, taintCause) and exists(Expr tainted | - tainted = e.getAChild() and - tainted.getUnspecifiedType() instanceof IntegralType and - isUserInput(source, taintCause) and - tainted(source, tainted) + allocSink(alloc, tainted) and + taintedWithPath(source, tainted, sourceNode, sinkNode) ) } -from Expr e, Expr source, string taintCause -where taintedAllocSize(e, source, taintCause) -select e, "This allocation size is derived from $@ and might overflow", source, - "user input (" + taintCause + ")" +from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause +where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause) +select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow", + source, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql index 19bee24a16d..80b5ee49e97 100644 --- a/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql +++ b/cpp/ql/src/Security/CWE/CWE-290/AuthenticationBypass.ql @@ -3,7 +3,7 @@ * @description Authentication by checking that the peer's address * matches a known IP or web address is unsafe as it is * vulnerable to spoofing attacks. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/user-controlled-bypass @@ -12,6 +12,7 @@ */ import semmle.code.cpp.security.TaintTracking +import TaintedWithPath predicate hardCodedAddressOrIP(StringLiteral txt) { exists(string s | s = txt.getValueText() | @@ -102,16 +103,21 @@ predicate useOfHardCodedAddressOrIP(Expr use) { * untrusted input then it might be vulnerable to a spoofing * attack. */ -predicate hardCodedAddressInCondition(Expr source, Expr condition) { - // One of the sub-expressions of the condition is tainted. - exists(Expr taintedExpr | taintedExpr.getParent+() = condition | tainted(source, taintedExpr)) and +predicate hardCodedAddressInCondition(Expr subexpression, Expr condition) { + subexpression = condition.getAChild+() and // One of the sub-expressions of the condition is a hard-coded // IP or web-address. - exists(Expr use | use.getParent+() = condition | useOfHardCodedAddressOrIP(use)) and + exists(Expr use | use = condition.getAChild+() | useOfHardCodedAddressOrIP(use)) and condition = any(IfStmt ifStmt).getCondition() } -from Expr source, Expr condition -where hardCodedAddressInCondition(source, condition) -select condition, "Untrusted input $@ might be vulnerable to a spoofing attack.", source, - source.toString() +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element sink) { hardCodedAddressInCondition(sink, _) } +} + +from Expr subexpression, Expr source, Expr condition, PathNode sourceNode, PathNode sinkNode +where + hardCodedAddressInCondition(subexpression, condition) and + taintedWithPath(source, subexpression, sourceNode, sinkNode) +select condition, sourceNode, sinkNode, + "Untrusted input $@ might be vulnerable to a spoofing attack.", source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index aa153779df1..3e84c0a87d9 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -2,7 +2,7 @@ * @name Cleartext storage of sensitive information in buffer * @description Storing sensitive information in cleartext can expose it * to an attacker. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/cleartext-storage-buffer @@ -14,12 +14,20 @@ import cpp import semmle.code.cpp.security.BufferWrite import semmle.code.cpp.security.TaintTracking import semmle.code.cpp.security.SensitiveExprs +import TaintedWithPath -from BufferWrite w, Expr taintedArg, Expr taintSource, string taintCause, SensitiveExpr dest +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { exists(BufferWrite w | w.getASource() = tainted) } +} + +from + BufferWrite w, Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, + string taintCause, SensitiveExpr dest where - tainted(taintSource, taintedArg) and + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and isUserInput(taintSource, taintCause) and w.getASource() = taintedArg and dest = w.getDest() -select w, "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", +select w, sourceNode, sinkNode, + "This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", taintSource, "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index e4f1e9c834a..000833cbb58 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -2,7 +2,7 @@ * @name Cleartext storage of sensitive information in an SQLite database * @description Storing sensitive information in a non-encrypted * database can expose it to an attacker. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/cleartext-storage-database @@ -13,6 +13,7 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.TaintTracking +import TaintedWithPath class UserInputIsSensitiveExpr extends SecurityOptions { override predicate isUserInput(Expr expr, string cause) { @@ -32,10 +33,21 @@ predicate sqlite_encryption_used() { any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%") } -from SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element taintedArg) { + exists(SqliteFunctionCall sqliteCall | + taintedArg = sqliteCall.getASource() and + not sqlite_encryption_used() + ) + } +} + +from + SensitiveExpr taintSource, Expr taintedArg, SqliteFunctionCall sqliteCall, PathNode sourceNode, + PathNode sinkNode where - tainted(taintSource, taintedArg) and - taintedArg = sqliteCall.getASource() and - not sqlite_encryption_used() -select sqliteCall, "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, + taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and + taintedArg = sqliteCall.getASource() +select sqliteCall, sourceNode, sinkNode, + "This SQLite call may store $@ in a non-encrypted SQLite database", taintSource, "sensitive information" diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index a10e3df0bdd..c5285fdac57 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -198,12 +198,12 @@ class InitializationFunction extends Function { ) or // If we have no definition, we look at SAL annotations - not this.isDefined() and + not this.hasDefinition() and this.getParameter(i).(SALParameter).isOut() and evidence = SuggestiveSALAnnotation() or // We have some external information that this function conditionally initializes - not this.isDefined() and + not this.hasDefinition() and any(ValidatedExternalCondInitFunction vc).isExternallyVerified(this, i) and evidence = ExternalEvidence() } @@ -406,7 +406,7 @@ class ConditionalInitializationFunction extends InitializationFunction { * Explicitly ignore pure virtual functions. */ - this.isDefined() and + this.hasDefinition() and this.paramNotReassignedAt(this, i, c) and not this instanceof PureVirtualFunction ) @@ -616,11 +616,11 @@ private predicate functionSignature(Function f, string qualifiedName, string typ * are never statically linked together. */ private Function getAPossibleDefinition(Function undefinedFunction) { - not undefinedFunction.isDefined() and + not undefinedFunction.hasDefinition() and exists(string qn, string typeSig | functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig) ) and - result.isDefined() + result.hasDefinition() } /** @@ -631,7 +631,7 @@ private Function getAPossibleDefinition(Function undefinedFunction) { */ private Function getTarget1(Call c) { result = VirtualDispatch::getAViableTarget(c) and - result.isDefined() + result.hasDefinition() } /** diff --git a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql index b940da029ec..e60f592b2af 100644 --- a/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql +++ b/cpp/ql/src/Security/CWE/CWE-807/TaintedCondition.ql @@ -3,7 +3,7 @@ * @description Using untrusted inputs in a statement that makes a * security decision makes code vulnerable to * attack. - * @kind problem + * @kind path-problem * @problem.severity warning * @precision medium * @id cpp/tainted-permissions-check @@ -12,14 +12,9 @@ */ import semmle.code.cpp.security.TaintTracking +import TaintedWithPath -/** - * Holds if there is an 'if' statement whose condition `condition` - * is influenced by tainted data `source`, and the body contains - * `raise` which escalates privilege. - */ -predicate cwe807violation(Expr source, Expr condition, Expr raise) { - tainted(source, condition) and +predicate sensitiveCondition(Expr condition, Expr raise) { raisesPrivilege(raise) and exists(IfStmt ifstmt | ifstmt.getCondition() = condition and @@ -27,7 +22,19 @@ predicate cwe807violation(Expr source, Expr condition, Expr raise) { ) } -from Expr source, Expr condition, Expr raise -where cwe807violation(source, condition, raise) -select condition, "Reliance on untrusted input $@ to raise privilege at $@", source, - source.toString(), raise, raise.toString() +class Configuration extends TaintTrackingConfiguration { + override predicate isSink(Element tainted) { sensitiveCondition(tainted, _) } +} + +/* + * Produce an alert if there is an 'if' statement whose condition `condition` + * is influenced by tainted data `source`, and the body contains + * `raise` which escalates privilege. + */ + +from Expr source, Expr condition, Expr raise, PathNode sourceNode, PathNode sinkNode +where + taintedWithPath(source, condition, sourceNode, sinkNode) and + sensitiveCondition(condition, raise) +select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@", + source, source.toString(), raise, raise.toString() diff --git a/cpp/ql/src/codeql-suites/cpp-code-scanning.qls b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls new file mode 100644 index 00000000000..27bff98ea5d --- /dev/null +++ b/cpp/ql/src/codeql-suites/cpp-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for C and C++ +- qlpack: codeql-cpp +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql index 5f89dac0c08..0e021ca7575 100644 --- a/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql +++ b/cpp/ql/src/jsf/4.13 Functions/AV Rule 114.ql @@ -30,7 +30,13 @@ predicate functionsMissingReturnStmt(Function f, ControlFlowNode blame) { ) and exists(ReturnStmt s | f.getAPredecessor() = s and - blame = s.getAPredecessor() + ( + blame = s.getAPredecessor() and + count(blame.getASuccessor()) = 1 + or + blame = s and + exists(ControlFlowNode pred | pred = s.getAPredecessor() | count(pred.getASuccessor()) != 1) + ) ) } diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index a1c7df902de..45ae614f88e 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-cpp version: 0.0.0 dbscheme: semmlecode.cpp.dbscheme suites: codeql-suites +extractor: cpp diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 67a2d11ff24..5aa9f43f48b 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -458,6 +458,15 @@ class Class extends UserType { exists(ClassDerivation d | d.getDerivedClass() = this and d = result) } + /** + * Gets class derivation number `index` of this class/struct, for example the + * `public B` is derivation 1 in the following code: + * ``` + * class D : public A, public B, public C { + * ... + * }; + * ``` + */ ClassDerivation getDerivation(int index) { exists(ClassDerivation d | d.getDerivedClass() = this and d.getIndex() = index and d = result) } @@ -900,6 +909,22 @@ class AbstractClass extends Class { class TemplateClass extends Class { TemplateClass() { usertypes(underlyingElement(this), _, 6) } + /** + * Gets a class instantiated from this template. + * + * For example for `MyTemplateClass` in the following code, the results are + * `MyTemplateClass` and `MyTemplateClass`: + * ``` + * template + * class MyTemplateClass { + * ... + * }; + * + * MyTemplateClass instance; + * + * MyTemplateClass instance; + * ``` + */ Class getAnInstantiation() { result.isConstructedFrom(this) and exists(result.getATemplateArgument()) diff --git a/cpp/ql/src/semmle/code/cpp/Comments.qll b/cpp/ql/src/semmle/code/cpp/Comments.qll index e517f8e7b0e..7f961bfd6f6 100644 --- a/cpp/ql/src/semmle/code/cpp/Comments.qll +++ b/cpp/ql/src/semmle/code/cpp/Comments.qll @@ -13,8 +13,20 @@ class Comment extends Locatable, @comment { override Location getLocation() { comments(underlyingElement(this), _, result) } + /** + * Gets the text of this comment, including the opening `//` or `/*`, and the closing `*``/` if + * present. + */ string getContents() { comments(underlyingElement(this), result, _) } + /** + * Gets the AST element this comment is associated with. For example, the comment in the + * following code is associated with the declaration of `j`. + * ``` + * int i; + * int j; // Comment on j + * ``` + */ Element getCommentedElement() { commentbinding(underlyingElement(this), unresolveElement(result)) } diff --git a/cpp/ql/src/semmle/code/cpp/Compilation.qll b/cpp/ql/src/semmle/code/cpp/Compilation.qll index 02d962844c8..691c0e08de3 100644 --- a/cpp/ql/src/semmle/code/cpp/Compilation.qll +++ b/cpp/ql/src/semmle/code/cpp/Compilation.qll @@ -21,9 +21,9 @@ private predicate idOf(@compilation x, int y) = equivalenceRelation(id/2)(x, y) * Three things happen to each file during a compilation: * * 1. The file is compiled by a real compiler, such as gcc or VC. - * 2. The file is parsed by Semmle's C++ front-end. + * 2. The file is parsed by the CodeQL C++ front-end. * 3. The parsed representation is converted to database tables by - * Semmle's extractor. + * the CodeQL extractor. * * This class provides CPU and elapsed time information for steps 2 and 3, * but not for step 1. @@ -40,6 +40,7 @@ class Compilation extends @compilation { /** Gets a file compiled during this invocation. */ File getAFileCompiled() { result = getFileCompiled(_) } + /** Gets the `i`th file compiled during this invocation */ File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) } /** diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 1d5603fe4f4..a0eaa7fa1d0 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -161,6 +161,7 @@ abstract class Declaration extends Locatable, @declaration { /** Holds if the declaration has a definition. */ predicate hasDefinition() { exists(this.getDefinition()) } + /** DEPRECATED: Use `hasDefinition` instead. */ predicate isDefined() { hasDefinition() } /** Gets the preferred location of this declaration, if any. */ @@ -303,7 +304,7 @@ abstract class DeclarationEntry extends Locatable { * available), or the name declared by this entry otherwise. */ string getCanonicalName() { - if getDeclaration().isDefined() + if getDeclaration().hasDefinition() then result = getDeclaration().getDefinition().getName() else result = getName() } diff --git a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll index f03f03783c1..37459602c03 100644 --- a/cpp/ql/src/semmle/code/cpp/Diagnostics.qll +++ b/cpp/ql/src/semmle/code/cpp/Diagnostics.qll @@ -11,6 +11,7 @@ class Diagnostic extends Locatable, @diagnostic { /** Gets the error code for this compiler message. */ string getTag() { diagnostics(underlyingElement(this), _, result, _, _, _) } + /** Holds if `s` is the error code for this compiler message. */ predicate hasTag(string s) { this.getTag() = s } /** diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 38e5efba6df..56e18fa055e 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -697,28 +697,188 @@ class Int128Type extends IntegralType { override string getCanonicalQLClass() { result = "Int128Type" } } +private newtype TTypeDomain = + TRealDomain() or + TComplexDomain() or + TImaginaryDomain() + /** - * The C/C++ floating point types. See 4.5. This includes `float`, - * `double` and `long double` types. - * ``` - * float f; - * double d; - * long double ld; - * ``` + * The type domain of a floating-point type. One of `RealDomain`, `ComplexDomain`, or + * `ImaginaryDomain`. + */ +class TypeDomain extends TTypeDomain { + /** Gets a textual representation of this type domain. */ + string toString() { none() } +} + +/** + * The type domain of a floating-point type that represents a real number. + */ +class RealDomain extends TypeDomain, TRealDomain { + final override string toString() { result = "real" } +} + +/** + * The type domain of a floating-point type that represents a complex number. + */ +class ComplexDomain extends TypeDomain, TComplexDomain { + final override string toString() { result = "complex" } +} + +/** + * The type domain of a floating-point type that represents an imaginary number. + */ +class ImaginaryDomain extends TypeDomain, TImaginaryDomain { + final override string toString() { result = "imaginary" } +} + +/** + * Data for floating-point types. + * + * kind: The original type kind. Can be any floating-point type kind. + * base: The numeric base of the number's representation. Can be 2 (binary) or 10 (decimal). + * domain: The type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + * realKind: The type kind of the corresponding real type. For example, the corresponding real type + * of `_Complex double` is `double`. + * extended: `true` if the number is an extended-precision floating-point number, such as + * `_Float32x`. + */ +private predicate floatingPointTypeMapping( + int kind, int base, TTypeDomain domain, int realKind, boolean extended +) { + // float + kind = 24 and base = 2 and domain = TRealDomain() and realKind = 24 and extended = false + or + // double + kind = 25 and base = 2 and domain = TRealDomain() and realKind = 25 and extended = false + or + // long double + kind = 26 and base = 2 and domain = TRealDomain() and realKind = 26 and extended = false + or + // _Complex float + kind = 27 and base = 2 and domain = TComplexDomain() and realKind = 24 and extended = false + or + // _Complex double + kind = 28 and base = 2 and domain = TComplexDomain() and realKind = 25 and extended = false + or + // _Complex long double + kind = 29 and base = 2 and domain = TComplexDomain() and realKind = 26 and extended = false + or + // _Imaginary float + kind = 30 and base = 2 and domain = TImaginaryDomain() and realKind = 24 and extended = false + or + // _Imaginary double + kind = 31 and base = 2 and domain = TImaginaryDomain() and realKind = 25 and extended = false + or + // _Imaginary long double + kind = 32 and base = 2 and domain = TImaginaryDomain() and realKind = 26 and extended = false + or + // __float128 + kind = 38 and base = 2 and domain = TRealDomain() and realKind = 38 and extended = false + or + // _Complex __float128 + kind = 39 and base = 2 and domain = TComplexDomain() and realKind = 38 and extended = false + or + // _Decimal32 + kind = 40 and base = 10 and domain = TRealDomain() and realKind = 40 and extended = false + or + // _Decimal64 + kind = 41 and base = 10 and domain = TRealDomain() and realKind = 41 and extended = false + or + // _Decimal128 + kind = 42 and base = 10 and domain = TRealDomain() and realKind = 42 and extended = false + or + // _Float32 + kind = 45 and base = 2 and domain = TRealDomain() and realKind = 45 and extended = false + or + // _Float32x + kind = 46 and base = 2 and domain = TRealDomain() and realKind = 46 and extended = true + or + // _Float64 + kind = 47 and base = 2 and domain = TRealDomain() and realKind = 47 and extended = false + or + // _Float64x + kind = 48 and base = 2 and domain = TRealDomain() and realKind = 48 and extended = true + or + // _Float128 + kind = 49 and base = 2 and domain = TRealDomain() and realKind = 49 and extended = false + or + // _Float128x + kind = 50 and base = 2 and domain = TRealDomain() and realKind = 50 and extended = true +} + +/** + * The C/C++ floating point types. See 4.5. This includes `float`, `double` and `long double`, the + * fixed-size floating-point types like `_Float32`, the extended-precision floating-point types like + * `_Float64x`, and the decimal floating-point types like `_Decimal32`. It also includes the complex + * and imaginary versions of all of these types. */ class FloatingPointType extends ArithmeticType { + final int base; + final TypeDomain domain; + final int realKind; + final boolean extended; + FloatingPointType() { exists(int kind | builtintypes(underlyingElement(this), _, kind, _, _, _) and - ( - kind >= 24 and kind <= 32 - or - kind >= 38 and kind <= 42 - or - kind >= 45 and kind <= 50 - ) + floatingPointTypeMapping(kind, base, domain, realKind, extended) ) } + + /** Gets the numeric base of this type's representation: 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of this type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final TypeDomain getDomain() { result = domain } + + /** + * Gets the corresponding real type of this type. For example, the corresponding real type of + * `_Complex double` is `double`. + */ + final RealNumberType getRealType() { + builtintypes(unresolveElement(result), _, realKind, _, _, _) + } + + /** Holds if this type is an extended precision floating-point type, such as `_Float32x`. */ + final predicate isExtendedPrecision() { extended = true } +} + +/** + * A floating-point type representing a real number. + */ +class RealNumberType extends FloatingPointType { + RealNumberType() { domain instanceof RealDomain } +} + +/** + * A floating-point type representing a complex number. + */ +class ComplexNumberType extends FloatingPointType { + ComplexNumberType() { domain instanceof ComplexDomain } +} + +/** + * A floating-point type representing an imaginary number. + */ +class ImaginaryNumberType extends FloatingPointType { + ImaginaryNumberType() { domain instanceof ImaginaryDomain } +} + +/** + * A floating-point type whose representation is base 2. + */ +class BinaryFloatingPointType extends FloatingPointType { + BinaryFloatingPointType() { base = 2 } +} + +/** + * A floating-point type whose representation is base 10. + */ +class DecimalFloatingPointType extends FloatingPointType { + DecimalFloatingPointType() { base = 10 } } /** @@ -727,7 +887,7 @@ class FloatingPointType extends ArithmeticType { * float f; * ``` */ -class FloatType extends FloatingPointType { +class FloatType extends RealNumberType, BinaryFloatingPointType { FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) } override string getCanonicalQLClass() { result = "FloatType" } @@ -739,7 +899,7 @@ class FloatType extends FloatingPointType { * double d; * ``` */ -class DoubleType extends FloatingPointType { +class DoubleType extends RealNumberType, BinaryFloatingPointType { DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) } override string getCanonicalQLClass() { result = "DoubleType" } @@ -751,7 +911,7 @@ class DoubleType extends FloatingPointType { * long double ld; * ``` */ -class LongDoubleType extends FloatingPointType { +class LongDoubleType extends RealNumberType, BinaryFloatingPointType { LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) } override string getCanonicalQLClass() { result = "LongDoubleType" } @@ -763,7 +923,7 @@ class LongDoubleType extends FloatingPointType { * __float128 f128; * ``` */ -class Float128Type extends FloatingPointType { +class Float128Type extends RealNumberType, BinaryFloatingPointType { Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) } override string getCanonicalQLClass() { result = "Float128Type" } @@ -775,7 +935,7 @@ class Float128Type extends FloatingPointType { * _Decimal32 d32; * ``` */ -class Decimal32Type extends FloatingPointType { +class Decimal32Type extends RealNumberType, DecimalFloatingPointType { Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) } override string getCanonicalQLClass() { result = "Decimal32Type" } @@ -787,7 +947,7 @@ class Decimal32Type extends FloatingPointType { * _Decimal64 d64; * ``` */ -class Decimal64Type extends FloatingPointType { +class Decimal64Type extends RealNumberType, DecimalFloatingPointType { Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) } override string getCanonicalQLClass() { result = "Decimal64Type" } @@ -799,7 +959,7 @@ class Decimal64Type extends FloatingPointType { * _Decimal128 d128; * ``` */ -class Decimal128Type extends FloatingPointType { +class Decimal128Type extends RealNumberType, DecimalFloatingPointType { Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) } override string getCanonicalQLClass() { result = "Decimal128Type" } diff --git a/cpp/ql/src/semmle/code/cpp/UserType.qll b/cpp/ql/src/semmle/code/cpp/UserType.qll index cbb7f39adbd..4484cde84de 100644 --- a/cpp/ql/src/semmle/code/cpp/UserType.qll +++ b/cpp/ql/src/semmle/code/cpp/UserType.qll @@ -38,7 +38,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @ override Specifier getASpecifier() { result = Type.super.getASpecifier() } override Location getLocation() { - if isDefined() + if hasDefinition() then result = this.getDefinitionLocation() else result = this.getADeclarationLocation() } diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index a508c929d9a..a9597fc72b5 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -23,6 +23,8 @@ predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunctio /** * A call to a library routine that frees memory. + * + * DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions). */ predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getFreedExpr() } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll index 626e50925f9..2d8b52f8622 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/RecursionPrevention.qll @@ -1,6 +1,6 @@ /** * DEPRECATED: Recursion through `DataFlow::Configuration` is impossible in - * Semmle Core 1.17 and above. There is no need for this module because it's + * any supported tooling. There is no need for this module because it's * impossible to accidentally depend on recursion through * `DataFlow::Configuration` in current releases. * diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..0dc3b8eff45 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,175 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index a0fd5dc4c50..1c6ab9a8c46 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -293,3 +293,27 @@ class DataFlowCall extends Expr { predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { + // Is the null pointer (or something that's not really a pointer) + exists(n.asExpr().getValue()) + or + // Isn't a pointer or is a pointer to const + forall(DerivedType dt | dt = n.asExpr().getActualType() | + dt.getBaseType().isConst() + or + dt.getBaseType() instanceof RoutineType + ) + or + // Isn't something we can track + n.asExpr() instanceof Call + // The above list of cases isn't exhaustive, but it narrows down the + // consistency alerts enough that most of them are interesting. +} diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll index bb6aa86b4e7..97371919b02 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Expr.qll @@ -2,6 +2,7 @@ import semmle.code.cpp.Element private import semmle.code.cpp.Enclosing private import semmle.code.cpp.internal.ResolveClass private import semmle.code.cpp.internal.AddressConstantExpression +private import semmle.code.cpp.models.implementations.Allocation /** * A C/C++ expression. @@ -804,8 +805,10 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr { * call the constructor of `T` but will not allocate memory. */ Expr getPlacementPointer() { - isStandardPlacementNewAllocator(this.getAllocator()) and - result = this.getAllocatorCall().getArgument(1) + result = + this + .getAllocatorCall() + .getArgument(this.getAllocator().(OperatorNewAllocationFunction).getPlacementArgument()) } } @@ -1194,12 +1197,6 @@ private predicate convparents(Expr child, int idx, Element parent) { ) } -private predicate isStandardPlacementNewAllocator(Function operatorNew) { - operatorNew.getName().matches("operator new%") and - operatorNew.getNumberOfParameters() = 2 and - operatorNew.getParameter(1).getType() instanceof VoidPointerType -} - // Pulled out for performance. See QL-796. private predicate hasNoConversions(Expr e) { not e.hasConversion() } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index d932ad30b87..dbeefae4880 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.security.Security private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.dataflow.DataFlow2 +private import semmle.code.cpp.ir.dataflow.DataFlow3 private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch private import semmle.code.cpp.models.interfaces.Taint @@ -143,7 +144,17 @@ private predicate writesVariable(StoreInstruction store, Variable var) { } /** - * A variable that has any kind of upper-bound check anywhere in the program + * A variable that has any kind of upper-bound check anywhere in the program. This is + * biased towards being inclusive because there are a lot of valid ways of doing an + * upper bounds checks if we don't consider where it occurs, for example: + * ``` + * if (x < 10) { sink(x); } + * + * if (10 > y) { sink(y); } + * + * if (z > 10) { z = 10; } + * sink(z); + * ``` */ // TODO: This coarse overapproximation, ported from the old taint tracking // library, could be replaced with an actual semantic check that a particular @@ -152,10 +163,10 @@ private predicate writesVariable(StoreInstruction store, Variable var) { // previously suppressed by this predicate by coincidence. private predicate hasUpperBoundsCheck(Variable var) { exists(RelationalOperation oper, VariableAccess access | - oper.getLeftOperand() = access and + oper.getAnOperand() = access and access.getTarget() = var and // Comparing to 0 is not an upper bound check - not oper.getRightOperand().getValue() = "0" + not oper.getAnOperand().getValue() = "0" ) } @@ -171,6 +182,7 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) { node = getNodeForSource(any(Expr e)) } +cached private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Expressions computed from tainted data are also tainted exists(CallInstruction call, int argIndex | call = i2 | @@ -187,11 +199,44 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { // Flow through pointer dereference i2.(LoadInstruction).getSourceAddress() = i1 or - i2.(UnaryInstruction).getUnary() = i1 + // Flow through partial reads of arrays and unions + i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and + not i1.isResultConflated() and + ( + i1.getResultType() instanceof ArrayType or + i1.getResultType() instanceof Union + ) or - i2.(ChiInstruction).getPartial() = i1 and + // Unary instructions tend to preserve enough information in practice that we + // want taint to flow through. + // The exception is `FieldAddressInstruction`. Together with the rule for + // `LoadInstruction` above and for `ChiInstruction` below, flow through + // `FieldAddressInstruction` could cause flow into one field to come out an + // unrelated field. This would happen across function boundaries, where the IR + // would not be able to match loads to stores. + i2.(UnaryInstruction).getUnary() = i1 and + ( + not i2 instanceof FieldAddressInstruction + or + i2.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union + ) + or + // Flow out of definition-by-reference + i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and not i2.isResultConflated() or + // Flow from an element to an array or union that contains it. + i2.(ChiInstruction).getPartial() = i1 and + not i2.isResultConflated() and + exists(Type t | i2.getResultLanguageType().hasType(t, false) | + t instanceof Union + or + t instanceof ArrayType + or + // Buffers of unknown size + t instanceof UnknownType + ) + or exists(BinaryInstruction bin | bin = i2 and predictableInstruction(i2.getAnOperand().getDef()) and @@ -348,6 +393,16 @@ private Element adjustedSink(DataFlow::Node sink) { result.(AssignOperation).getAnOperand() = sink.asExpr() } +/** + * Holds if `tainted` may contain taint from `source`. + * + * A tainted expression is either directly user input, or is + * computed from user input in a way that users can probably + * control the exact output of the computation. + * + * This doesn't include data flow through global variables. + * If you need that you must call `taintedIncludingGlobalVars`. + */ cached predicate tainted(Expr source, Element tainted) { exists(DefaultTaintTrackingCfg cfg, DataFlow::Node sink | @@ -356,6 +411,21 @@ predicate tainted(Expr source, Element tainted) { ) } +/** + * Holds if `tainted` may contain taint from `source`, where the taint passed + * through a global variable named `globalVar`. + * + * A tainted expression is either directly user input, or is + * computed from user input in a way that users can probably + * control the exact output of the computation. + * + * This version gives the same results as tainted but also includes + * data flow through global variables. + * + * The parameter `globalVar` is the qualified name of the last global variable + * used to move the value from source to tainted. If the taint did not pass + * through a global variable, then `globalVar = ""`. + */ cached predicate taintedIncludingGlobalVars(Expr source, Element tainted, string globalVar) { tainted(source, tainted) and @@ -373,11 +443,245 @@ predicate taintedIncludingGlobalVars(Expr source, Element tainted, string global ) } +/** + * Gets the global variable whose qualified name is `id`. Use this predicate + * together with `taintedIncludingGlobalVars`. Example: + * + * ``` + * exists(string varName | + * taintedIncludingGlobalVars(source, tainted, varName) and + * var = globalVarFromId(varName) + * ) + * ``` + */ GlobalOrNamespaceVariable globalVarFromId(string id) { id = result.getQualifiedName() } +/** + * Resolve potential target function(s) for `call`. + * + * If `call` is a call through a function pointer (`ExprCall`) or + * targets a virtual method, simple data flow analysis is performed + * in order to identify target(s). + */ Function resolveCall(Call call) { exists(CallInstruction callInstruction | callInstruction.getAST() = call and result = Dispatch::viableCallable(callInstruction) ) } + +/** + * Provides definitions for augmenting source/sink pairs with data-flow paths + * between them. From a `@kind path-problem` query, import this module in the + * global scope, extend `TaintTrackingConfiguration`, and use `taintedWithPath` + * in place of `tainted`. + * + * Importing this module will also import the query predicates that contain the + * taint paths. + */ +module TaintedWithPath { + private newtype TSingleton = MkSingleton() + + /** + * A taint-tracking configuration that matches sources and sinks in the same + * way as the `tainted` predicate. + * + * Override `isSink` and `taintThroughGlobals` as needed, but do not provide + * a characteristic predicate. + */ + class TaintTrackingConfiguration extends TSingleton { + /** Override this to specify which elements are sinks in this configuration. */ + abstract predicate isSink(Element e); + + /** + * Override this predicate to `any()` to allow taint to flow through global + * variables. + */ + predicate taintThroughGlobals() { none() } + + /** Gets a textual representation of this element. */ + string toString() { result = "TaintTrackingConfiguration" } + } + + private class AdjustedConfiguration extends DataFlow3::Configuration { + AdjustedConfiguration() { this = "AdjustedConfiguration" } + + override predicate isSource(DataFlow::Node source) { source = getNodeForSource(_) } + + override predicate isSink(DataFlow::Node sink) { + exists(TaintTrackingConfiguration cfg | cfg.isSink(adjustedSink(sink))) + } + + override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + instructionTaintStep(n1.asInstruction(), n2.asInstruction()) + or + exists(TaintTrackingConfiguration cfg | cfg.taintThroughGlobals() | + writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable)) + or + readsVariable(n2.asInstruction(), n1.asVariable().(GlobalOrNamespaceVariable)) + ) + } + + override predicate isBarrier(DataFlow::Node node) { nodeIsBarrier(node) } + + override predicate isBarrierIn(DataFlow::Node node) { nodeIsBarrierIn(node) } + } + + /* + * A sink `Element` may map to multiple `DataFlowX::PathNode`s via (the + * inverse of) `adjustedSink`. For example, an `Expr` maps to all its + * conversions, and a `Variable` maps to all loads and stores from it. Because + * the path node is part of the tuple that constitutes the alert, this leads + * to duplicate alerts. + * + * To avoid showing duplicates, we edit the graph to replace the final node + * coming from the data-flow library with a node that matches exactly the + * `Element` sink that's requested. + * + * The same is done for sources. + */ + + private newtype TPathNode = + TWrapPathNode(DataFlow3::PathNode n) or + // There's a single newtype constructor for both sources and sinks since + // that makes it easiest to deal with the case where source = sink. + TEndpointPathNode(Element e) { + exists(AdjustedConfiguration cfg, DataFlow3::Node sourceNode, DataFlow3::Node sinkNode | + cfg.hasFlow(sourceNode, sinkNode) + | + sourceNode = getNodeForSource(e) + or + e = adjustedSink(sinkNode) and + exists(TaintTrackingConfiguration ttCfg | ttCfg.isSink(e)) + ) + } + + /** An opaque type used for the nodes of a data-flow path. */ + class PathNode extends TPathNode { + /** Gets a textual representation of this element. */ + string toString() { none() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + none() + } + } + + private class WrapPathNode extends PathNode, TWrapPathNode { + DataFlow3::PathNode inner() { this = TWrapPathNode(result) } + + override string toString() { result = this.inner().toString() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.inner().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class EndpointPathNode extends PathNode, TEndpointPathNode { + Expr inner() { this = TEndpointPathNode(result) } + + override string toString() { result = this.inner().toString() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this + .inner() + .getLocation() + .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** A PathNode whose `Element` is a source. It may also be a sink. */ + private class InitialPathNode extends EndpointPathNode { + InitialPathNode() { exists(getNodeForSource(this.inner())) } + } + + /** A PathNode whose `Element` is a sink. It may also be a source. */ + private class FinalPathNode extends EndpointPathNode { + FinalPathNode() { exists(TaintTrackingConfiguration cfg | cfg.isSink(this.inner())) } + } + + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), b.(WrapPathNode).inner()) + or + // To avoid showing trivial-looking steps, we _replace_ the last node instead + // of adding an edge out of it. + exists(WrapPathNode sinkNode | + DataFlow3::PathGraph::edges(a.(WrapPathNode).inner(), sinkNode.inner()) and + b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode()) + ) + or + // Same for the first node + exists(WrapPathNode sourceNode | + DataFlow3::PathGraph::edges(sourceNode.inner(), b.(WrapPathNode).inner()) and + sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) + ) + or + // Finally, handle the case where the path goes directly from a source to a + // sink, meaning that they both need to be translated. + exists(WrapPathNode sinkNode, WrapPathNode sourceNode | + DataFlow3::PathGraph::edges(sourceNode.inner(), sinkNode.inner()) and + sourceNode.inner().getNode() = getNodeForSource(a.(InitialPathNode).inner()) and + b.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode()) + ) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `tainted` may contain taint from `source`, where `sourceNode` and + * `sinkNode` are the corresponding `PathNode`s that can be used in a query + * to provide path explanations. Extend `TaintTrackingConfiguration` to use + * this predicate. + * + * A tainted expression is either directly user input, or is computed from + * user input in a way that users can probably control the exact output of + * the computation. + */ + predicate taintedWithPath(Expr source, Element tainted, PathNode sourceNode, PathNode sinkNode) { + exists(AdjustedConfiguration cfg, DataFlow3::Node flowSource, DataFlow3::Node flowSink | + source = sourceNode.(InitialPathNode).inner() and + flowSource = getNodeForSource(source) and + cfg.hasFlow(flowSource, flowSink) and + tainted = adjustedSink(flowSink) and + tainted = sinkNode.(FinalPathNode).inner() + ) + } + + private predicate isGlobalVariablePathNode(WrapPathNode n) { + n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable + } + + private predicate edgesWithoutGlobals(PathNode a, PathNode b) { + edges(a, b) and + not isGlobalVariablePathNode(a) and + not isGlobalVariablePathNode(b) + } + + /** + * Holds if `tainted` can be reached from a taint source without passing + * through a global variable. + */ + predicate taintedWithoutGlobals(Element tainted) { + exists(PathNode sourceNode, FinalPathNode sinkNode | + sourceNode.(WrapPathNode).inner().getNode() = getNodeForSource(_) and + edgesWithoutGlobals+(sourceNode, sinkNode) and + tainted = sinkNode.inner() + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index abb62b9a021..1dd1d9ac4cc 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -70,8 +70,7 @@ private module VirtualDispatch { // Call return exists(DataFlowCall call, ReturnKind returnKind | other = getAnOutNode(call, returnKind) and - src.(ReturnNode).getKind() = returnKind and - call.getStaticCallTarget() = src.getEnclosingCallable() + returnNodeWithKindAndEnclosingCallable(src, returnKind, call.getStaticCallTarget()) ) and allowFromArg = false or @@ -125,6 +124,18 @@ private module VirtualDispatch { } } + /** + * A ReturnNode with its ReturnKind and its enclosing callable. + * + * Used to fix a join ordering issue in flowsFrom. + */ + private predicate returnNodeWithKindAndEnclosingCallable( + ReturnNode node, ReturnKind kind, DataFlowCallable callable + ) { + node.getKind() = kind and + node.getEnclosingCallable() = callable + } + /** Call through a function pointer. */ private class DataSensitiveExprCall extends DataSensitiveCall { DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 7d2d728b67e..a1daeb66411 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..0dc3b8eff45 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,175 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index 83e5d5eb06b..51290bc3293 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -24,7 +24,9 @@ class ArgumentNode extends InstructionNode { DataFlowCall getCall() { this.argumentOf(result, _) } } -private newtype TReturnKind = TNormalReturnKind() +private newtype TReturnKind = + TNormalReturnKind() or + TIndirectReturnKind(ParameterIndex index) /** * A return kind. A return kind describes how a value can be returned @@ -32,23 +34,76 @@ private newtype TReturnKind = TNormalReturnKind() */ class ReturnKind extends TReturnKind { /** Gets a textual representation of this return kind. */ - string toString() { result = "return" } + abstract string toString(); +} + +private class NormalReturnKind extends ReturnKind, TNormalReturnKind { + override string toString() { result = "return" } +} + +private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind { + ParameterIndex index; + + IndirectReturnKind() { this = TIndirectReturnKind(index) } + + override string toString() { result = "outparam[" + index.toString() + "]" } } /** A data flow node that occurs as the result of a `ReturnStmt`. */ class ReturnNode extends InstructionNode { - ReturnNode() { exists(ReturnValueInstruction ret | this.getInstruction() = ret.getReturnValue()) } + Instruction primary; + + ReturnNode() { + exists(ReturnValueInstruction ret | instr = ret.getReturnValue() and primary = ret) + or + exists(ReturnIndirectionInstruction rii | + instr = rii.getSideEffectOperand().getAnyDef() and primary = rii + ) + } /** Gets the kind of this returned value. */ - ReturnKind getKind() { result = TNormalReturnKind() } + abstract ReturnKind getKind(); +} + +class ReturnValueNode extends ReturnNode { + override ReturnValueInstruction primary; + + override ReturnKind getKind() { result = TNormalReturnKind() } +} + +class ReturnIndirectionNode extends ReturnNode { + override ReturnIndirectionInstruction primary; + + override ReturnKind getKind() { result = TIndirectReturnKind(primary.getParameter().getIndex()) } } /** A data flow node that represents the output of a call. */ class OutNode extends InstructionNode { - override CallInstruction instr; + OutNode() { + instr instanceof CallInstruction or + instr instanceof WriteSideEffectInstruction + } /** Gets the underlying call. */ - DataFlowCall getCall() { result = instr } + abstract DataFlowCall getCall(); + + abstract ReturnKind getReturnKind(); +} + +private class CallOutNode extends OutNode { + override CallInstruction instr; + + override DataFlowCall getCall() { result = instr } + + override ReturnKind getReturnKind() { result instanceof NormalReturnKind } +} + +private class SideEffectOutNode extends OutNode { + override WriteSideEffectInstruction instr; + + override DataFlowCall getCall() { result = instr.getPrimaryInstruction() } + + override ReturnKind getReturnKind() { result = TIndirectReturnKind(instr.getIndex()) } } /** @@ -57,7 +112,7 @@ class OutNode extends InstructionNode { */ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { result.getCall() = call and - kind = TNormalReturnKind() + result.getReturnKind() = kind } /** @@ -131,7 +186,12 @@ private class ArrayContent extends Content, TArrayContent { * value of `node1`. */ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { - none() // stub implementation + exists(FieldAddressInstruction fa, StoreInstruction store | + node1.asInstruction() = store and + store.getDestinationAddress() = fa and + node2.asInstruction().(ChiInstruction).getPartial() = store and + f.(FieldContent).getField() = fa.getField() + ) } /** @@ -140,7 +200,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) { * `node2`. */ predicate readStep(Node node1, Content f, Node node2) { - none() // stub implementation + exists(FieldAddressInstruction fa, LoadInstruction load | + load.getSourceAddress() = fa and + node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and + fa.getField() = f.(FieldContent).getField() and + load = node2.asInstruction() + ) } /** @@ -154,7 +219,7 @@ Type getErasedRepr(Type t) { } /** Gets a string representation of a type returned by `getErasedRepr`. */ -string ppReprType(Type t) { result = t.toString() } +string ppReprType(Type t) { none() } // stub implementation /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from @@ -202,3 +267,16 @@ class DataFlowCall extends CallInstruction { predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { + // The rules for whether an IR argument gets a post-update node are too + // complex to model here. + any() +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index e19912a63ee..8b0ade838dd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -55,7 +55,7 @@ class Node extends TIRDataFlowNode { Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() } /** Gets the parameter corresponding to this node, if any. */ - Parameter asParameter() { result = this.(ParameterNode).getParameter() } + Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() } /** * Gets the variable corresponding to this node, if any. This can be used for @@ -63,6 +63,18 @@ class Node extends TIRDataFlowNode { */ Variable asVariable() { result = this.(VariableNode).getVariable() } + /** + * Gets the expression that is partially defined by this node, if any. + * + * Partial definitions are created for field stores (`x.y = taint();` is a partial + * definition of `x`), and for calls that may change the value of an object (so + * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is + * a partial definition of `&x`). + */ + Expr asPartialDefinition() { + result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression() + } + /** * DEPRECATED: See UninitializedNode. * @@ -96,6 +108,9 @@ class Node extends TIRDataFlowNode { string toString() { none() } // overridden by subclasses } +/** + * An instruction, viewed as a node in a data flow graph. + */ class InstructionNode extends Node, TInstructionNode { Instruction instr; @@ -143,26 +158,45 @@ class ExprNode extends InstructionNode { } /** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. + * A node representing a `Parameter`. This includes both explicit parameters such + * as `x` in `f(x)` and implicit parameters such as `this` in `x.f()` */ class ParameterNode extends InstructionNode { - override InitializeParameterInstruction instr; + ParameterNode() { + instr instanceof InitializeParameterInstruction + or + instr instanceof InitializeThisInstruction + } /** * Holds if this node is the parameter of `c` at the specified (zero-based) * position. The implicit `this` parameter is considered to have index `-1`. */ - predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } + predicate isParameterOf(Function f, int i) { none() } // overriden by subclasses +} +/** + * The value of a parameter at function entry, viewed as a node in a data + * flow graph. + */ +private class ExplicitParameterNode extends ParameterNode { + override InitializeParameterInstruction instr; + + override predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } + + /** Gets the parameter corresponding to this node. */ Parameter getParameter() { result = instr.getParameter() } override string toString() { result = instr.getParameter().toString() } } -private class ThisParameterNode extends InstructionNode { +private class ThisParameterNode extends ParameterNode { override InitializeThisInstruction instr; + override predicate isParameterOf(Function f, int i) { + i = -1 and instr.getEnclosingFunction() = f + } + override string toString() { result = "this" } } @@ -204,6 +238,38 @@ abstract class PostUpdateNode extends InstructionNode { abstract Node getPreUpdateNode(); } +/** + * The base class for nodes that perform "partial definitions". + * + * In contrast to a normal "definition", which provides a new value for + * something, a partial definition is an expression that may affect a + * value, but does not necessarily replace it entirely. For example: + * ``` + * x.y = 1; // a partial definition of the object `x`. + * x.y.z = 1; // a partial definition of the object `x.y`. + * x.setY(1); // a partial definition of the object `x`. + * setY(&x); // a partial definition of the object `x`. + * ``` + */ +abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { } + +private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode { + override ChiInstruction instr; + + ExplicitFieldStoreQualifierNode() { + not instr.isResultConflated() and + exists(StoreInstruction store, FieldInstruction field | + instr.getPartial() = store and field = store.getDestinationAddress() + ) + } + + // There might be multiple `ChiInstructions` that has a particular instruction as + // the total operand - so this definition gives consistency errors in + // DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications + // this consistency failure has. + override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() } +} + /** * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference. @@ -239,6 +305,17 @@ class DefinitionByReferenceNode extends InstructionNode { Parameter getParameter() { exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) } + + override string toString() { + // This string should be unique enough to be helpful but common enough to + // avoid storing too many different strings. + result = + instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget().getName() + + " output argument" + or + not exists(instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget()) and + result = "output argument" + } } /** @@ -277,6 +354,10 @@ class VariableNode extends Node, TVariableNode { */ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } +/** + * Gets the `Node` corresponding to a definition by reference of the variable + * that is passed as `argument` of a call. + */ DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e } /** @@ -289,12 +370,12 @@ ExprNode exprNode(Expr e) { result.getExpr() = e } * Gets the `Node` corresponding to `e`, if any. Here, `e` may be a * `Conversion`. */ -ExprNode convertedExprNode(Expr e) { result.getExpr() = e } +ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e } /** * Gets the `Node` corresponding to the value of `p` at function entry. */ -ParameterNode parameterNode(Parameter p) { result.getParameter() = p } +ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p } /** Gets the `VariableNode` corresponding to the variable `v`. */ VariableNode variableNode(Variable v) { result.getVariable() = v } @@ -323,6 +404,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction()) } +cached private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) { iTo.(CopyInstruction).getSourceValue() = iFrom or @@ -348,6 +430,28 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for now. iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + // The next two rules allow flow from partial definitions in setters to succeeding loads in the caller. + // First, we add flow from write side-effects to non-conflated chi instructions through their + // partial operands. Consider the following example: + // ``` + // void setX(Point* p, int new_x) { + // p->x = new_x; + // } + // ... + // setX(&p, taint()); + // ``` + // Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to + // `setX`, which will be melded into `p` through a chi instruction. + iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and + not iTo.isResultConflated() + or + // Next, we add flow from non-conflated chi instructions to loads (even when they are not precise). + // This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above. + exists(ChiInstruction chi | iFrom = chi | + not chi.isResultConflated() and + iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi + ) + or // Flow through modeled functions modelFlow(iFrom, iTo) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 833c929ecc5..9a75ca19154 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -12,7 +12,9 @@ private newtype TIRType = TIRBooleanType(int byteSize) { Language::hasBooleanType(byteSize) } or TIRSignedIntegerType(int byteSize) { Language::hasSignedIntegerType(byteSize) } or TIRUnsignedIntegerType(int byteSize) { Language::hasUnsignedIntegerType(byteSize) } or - TIRFloatingPointType(int byteSize) { Language::hasFloatingPointType(byteSize) } or + TIRFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + Language::hasFloatingPointType(byteSize, base, domain) + } or TIRAddressType(int byteSize) { Language::hasAddressType(byteSize) } or TIRFunctionAddressType(int byteSize) { Language::hasFunctionAddressType(byteSize) } or TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) { @@ -104,7 +106,7 @@ private class IRSizedType extends IRType { this = TIRBooleanType(byteSize) or this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) or + this = TIRFloatingPointType(byteSize, _, _) or this = TIRAddressType(byteSize) or this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) @@ -133,7 +135,7 @@ class IRNumericType extends IRSizedType { IRNumericType() { this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) + this = TIRFloatingPointType(byteSize, _, _) } } @@ -171,14 +173,43 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - final override string toString() { result = "float" + byteSize.toString() } + final private int base; + final private Language::TypeDomain domain; + + IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) } + + final override string toString() { + result = getDomainPrefix() + getBaseString() + byteSize.toString() + } final override Language::LanguageType getCanonicalLanguageType() { - result = Language::getCanonicalFloatingPointType(byteSize) + result = Language::getCanonicalFloatingPointType(byteSize, base, domain) } pragma[noinline] final override int getByteSize() { result = byteSize } + + /** Gets the numeric base of the type. Can be either 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final Language::TypeDomain getDomain() { result = domain } + + private string getBaseString() { + base = 2 and result = "float" + or + base = 10 and result = "decimal" + } + + private string getDomainPrefix() { + domain instanceof Language::RealDomain and result = "" + or + domain instanceof Language::ComplexDomain and result = "c" + or + domain instanceof Language::ImaginaryDomain and result = "i" + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index fc9d0758125..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index fc9d0758125..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index fb7dc173812..22f104e12c8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -206,7 +206,44 @@ abstract class TranslatedCall extends TranslatedExpr { predicate hasPreciseSideEffect() { exists(getSideEffects()) } - TranslatedSideEffects getSideEffects() { result.getCall() = expr } + final TranslatedSideEffects getSideEffects() { result.getExpr() = expr } +} + +abstract class TranslatedSideEffects extends TranslatedElement { + abstract Expr getExpr(); + + final override Locatable getAST() { result = getExpr() } + + final override Function getFunction() { result = getExpr().getEnclosingFunction() } + + override TranslatedElement getChild(int i) { + result = + rank[i + 1](TranslatedSideEffect tse, int isWrite, int index | + ( + tse.getCall() = getExpr() and + tse.getArgumentIndex() = index and + if tse.isWrite() then isWrite = 1 else isWrite = 0 + ) + | + tse order by isWrite, index + ) + } + + final override Instruction getChildSuccessor(TranslatedElement te) { + exists(int i | + getChild(i) = te and + if exists(getChild(i + 1)) + then result = getChild(i + 1).getFirstInstruction() + else result = getParent().getChildSuccessor(this) + ) + } + + /** + * Gets the `TranslatedFunction` containing this expression. + */ + final TranslatedFunction getEnclosingFunction() { + result = getTranslatedFunction(getExpr().getEnclosingFunction()) + } } /** @@ -287,6 +324,16 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { override predicate hasWriteSideEffect() { not expr.getTarget().(SideEffectFunction).hasOnlySpecificWriteSideEffects() } + + override Instruction getQualifierResult() { + hasQualifier() and + result = getQualifier().getResult() + } + + override predicate hasQualifier() { + exists(getQualifier()) and + not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) + } } /** @@ -308,56 +355,27 @@ class TranslatedStructorCall extends TranslatedFunctionCall { override predicate hasQualifier() { any() } } -class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { - Call expr; +class TranslatedAllocationSideEffects extends TranslatedSideEffects, + TTranslatedAllocationSideEffects { + AllocationExpr expr; - TranslatedSideEffects() { this = TTranslatedSideEffects(expr) } + TranslatedAllocationSideEffects() { this = TTranslatedAllocationSideEffects(expr) } - override string toString() { result = "(side effects for " + expr.toString() + ")" } + final override AllocationExpr getExpr() { result = expr } - override Locatable getAST() { result = expr } + override string toString() { result = "(allocation side effects for " + expr.toString() + ")" } - Call getCall() { result = expr } - - override TranslatedElement getChild(int i) { - result = - rank[i + 1](TranslatedSideEffect tse, int isWrite, int index | - ( - tse.getCall() = getCall() and - tse.getArgumentIndex() = index and - if tse.isWrite() then isWrite = 1 else isWrite = 0 - ) - | - tse order by isWrite, index - ) - } - - override Instruction getChildSuccessor(TranslatedElement te) { - exists(int i | - getChild(i) = te and - if exists(getChild(i + 1)) - then result = getChild(i + 1).getFirstInstruction() - else result = getParent().getChildSuccessor(this) - ) - } + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { - expr.getTarget() instanceof AllocationFunction and opcode instanceof Opcode::InitializeDynamicAllocation and tag = OnlyInstructionTag() and type = getUnknownType() } - override Instruction getFirstInstruction() { - if expr.getTarget() instanceof AllocationFunction - then result = getInstruction(OnlyInstructionTag()) - else result = getChild(0).getFirstInstruction() - } - override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { tag = OnlyInstructionTag() and kind = gotoEdge() and - expr.getTarget() instanceof AllocationFunction and if exists(getChild(0)) then result = getChild(0).getFirstInstruction() else result = getParent().getChildSuccessor(this) @@ -371,23 +389,34 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { tag = OnlyInstructionTag() and - result = getTranslatedExpr(expr).getInstruction(CallTag()) + if expr instanceof NewOrNewArrayExpr + then result = getTranslatedAllocatorCall(expr).getInstruction(CallTag()) + else result = getTranslatedExpr(expr).getInstruction(CallTag()) } - - /** - * Gets the `TranslatedFunction` containing this expression. - */ - final TranslatedFunction getEnclosingFunction() { - result = getTranslatedFunction(expr.getEnclosingFunction()) - } - - /** - * Gets the `Function` containing this expression. - */ - override Function getFunction() { result = expr.getEnclosingFunction() } } -class TranslatedStructorCallSideEffects extends TranslatedSideEffects { +class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSideEffects { + Call expr; + + TranslatedCallSideEffects() { this = TTranslatedCallSideEffects(expr) } + + override string toString() { result = "(side effects for " + expr.toString() + ")" } + + override Call getExpr() { result = expr } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() } + + override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } + + override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getTranslatedExpr(expr).getInstruction(CallTag()) + } +} + +class TranslatedStructorCallSideEffects extends TranslatedCallSideEffects { TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType t) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 9b9c690990f..2f143bf02ca 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -442,17 +442,30 @@ newtype TTranslatedElement = // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` - TTranslatedSideEffects(Call expr) { - exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or - expr instanceof ConstructorCall or - expr.getTarget() instanceof AllocationFunction - } or // A precise side effect of an argument to a `Call` + TTranslatedCallSideEffects(Call expr) { + // Exclude allocations such as `malloc` (which happen to also be function calls). + // Both `TranslatedCallSideEffects` and `TranslatedAllocationSideEffects` generate + // the same side effects for its children as they both extend the `TranslatedSideEffects` + // class. + // Note: We can separate allocation side effects and call side effects into two + // translated elements as no call can be both a `ConstructorCall` and an `AllocationExpr`. + not expr instanceof AllocationExpr and + ( + exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or + expr instanceof ConstructorCall + ) + } or + // The side effects of an allocation, i.e. `new`, `new[]` or `malloc` + TTranslatedAllocationSideEffects(AllocationExpr expr) or + // A precise side effect of an argument to a `Call` TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) { ( expr = call.getArgument(n).getFullyConverted() or expr = call.getQualifier().getFullyConverted() and - n = -1 + n = -1 and + // Exclude calls to static member functions. They don't modify the qualifier + not exists(MemberFunction func | func = call.getTarget() and func.isStatic()) ) and ( call.getTarget().(SideEffectFunction).hasSpecificReadSideEffect(n, _) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index c6c53a1842b..c072aae1258 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -1100,13 +1100,36 @@ private Opcode binaryBitwiseOpcode(BinaryBitwiseOperation expr) { } private Opcode binaryArithmeticOpcode(BinaryArithmeticOperation expr) { - expr instanceof AddExpr and result instanceof Opcode::Add + ( + expr instanceof AddExpr + or + expr instanceof ImaginaryRealAddExpr + or + expr instanceof RealImaginaryAddExpr + ) and + result instanceof Opcode::Add or - expr instanceof SubExpr and result instanceof Opcode::Sub + ( + expr instanceof SubExpr + or + expr instanceof ImaginaryRealSubExpr + or + expr instanceof RealImaginarySubExpr + ) and + result instanceof Opcode::Sub or - expr instanceof MulExpr and result instanceof Opcode::Mul + ( + expr instanceof MulExpr + or + expr instanceof ImaginaryMulExpr + ) and + result instanceof Opcode::Mul or - expr instanceof DivExpr and result instanceof Opcode::Div + ( + expr instanceof DivExpr or + expr instanceof ImaginaryDivExpr + ) and + result instanceof Opcode::Div or expr instanceof RemExpr and result instanceof Opcode::Rem or @@ -1649,6 +1672,11 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect final override int getNumberOfArguments() { result = expr.getAllocatorCall().getNumberOfArguments() + or + // Make sure there's a result even when there is no allocator, as otherwise + // TranslatedCall::getChild() will not return the side effects for this call. + not exists(expr.getAllocatorCall()) and + result = 0 } final override TranslatedExpr getArgument(int index) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 1bfc1c8275f..67b9622c3be 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -49,6 +49,11 @@ CppType getEllipsisVariablePRValueType() { CppType getEllipsisVariableGLValueType() { result = getTypeForGLValue(any(UnknownType t)) } +/** + * Holds if the function returns a value, as opposed to returning `void`. + */ +predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instanceof VoidType } + /** * Represents the IR translation of a function. This is the root elements for * all other elements associated with this function. @@ -312,7 +317,7 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { /** * Holds if the function has a non-`void` return type. */ - final predicate hasReturnValue() { not func.getUnspecifiedType() instanceof VoidType } + final predicate hasReturnValue() { hasReturnValue(func) } /** * Gets the single `UnmodeledDefinition` instruction for this function. @@ -454,7 +459,7 @@ abstract class TranslatedParameter extends TranslatedElement { result = getInstruction(InitializerVariableAddressTag()) or operandTag instanceof LoadOperandTag and - result = getInstruction(InitializerStoreTag()) + result = getTranslatedFunction(getFunction()).getUnmodeledDefinitionInstruction() ) or tag = InitializerIndirectStoreTag() and @@ -744,4 +749,9 @@ class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect { operandTag = sideEffectOperand() and result = getUnknownType() } + + final override IRVariable getInstructionVariable(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getIRUserVariable(getFunction(), param) + } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index 88a7d4c99ea..a4c9d487437 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -131,8 +131,11 @@ abstract class TranslatedReturnStmt extends TranslatedStmt { } } +/** + * The IR translation of a `return` statement that returns a value. + */ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization { - TranslatedReturnValueStmt() { stmt.hasExpr() } + TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) } final override Instruction getInitializationSuccessor() { result = getEnclosingFunction().getReturnSuccessorInstruction() @@ -147,8 +150,49 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() } } +/** + * The IR translation of a `return` statement that returns an expression of `void` type. + */ +class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt { + TranslatedReturnVoidExpressionStmt() { + stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction()) + } + + override TranslatedElement getChild(int id) { + id = 0 and + result = getExpr() + } + + override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::NoOp and + resultType = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getEnclosingFunction().getReturnSuccessorInstruction() and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getExpr() and + result = getInstruction(OnlyInstructionTag()) + } + + private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) } +} + +/** + * The IR translation of a `return` statement that does not return a value. This includes implicit + * return statements at the end of `void`-returning functions. + */ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { - TranslatedReturnVoidStmt() { not stmt.hasExpr() } + TranslatedReturnVoidStmt() { + not stmt.hasExpr() and not hasReturnValue(stmt.getEnclosingFunction()) + } override TranslatedElement getChild(int id) { none() } @@ -169,6 +213,33 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt { override Instruction getChildSuccessor(TranslatedElement child) { none() } } +/** + * The IR translation of an implicit `return` statement generated by the extractor to handle control + * flow that reaches the end of a non-`void`-returning function body. Since such control flow + * produces undefined behavior, we simply generate an `Unreached` instruction to prevent that flow + * from continuing on to pollute other analysis. The assumption is that the developer is certain + * that the implicit `return` is unreachable, even if the compiler cannot prove it. + */ +class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt { + TranslatedUnreachableReturnStmt() { + not stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) + } + + override TranslatedElement getChild(int id) { none() } + + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::Unreached and + resultType = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } + + override Instruction getChildSuccessor(TranslatedElement child) { none() } +} + /** * The IR translation of a C++ `try` statement. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index fc9d0758125..38216872f2b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 9e8044ede4f..d297097abd9 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -86,9 +86,15 @@ predicate hasUnsignedIntegerType(int byteSize) { } /** - * Holds if an `IRFloatingPointType` with the specified `byteSize` should exist. + * Holds if an `IRFloatingPointType` with the specified size, base, and type domain should exist. */ -predicate hasFloatingPointType(int byteSize) { byteSize = any(FloatingPointType type).getSize() } +predicate hasFloatingPointType(int byteSize, int base, TypeDomain domain) { + exists(FloatingPointType type | + byteSize = type.getSize() and + base = type.getBase() and + domain = type.getDomain() + ) +} private predicate isPointerIshType(Type type) { type instanceof PointerType @@ -159,8 +165,13 @@ private IRType getIRTypeForPRValue(Type type) { isUnsignedIntegerType(unspecifiedType) and result.(IRUnsignedIntegerType).getByteSize() = type.getSize() or - unspecifiedType instanceof FloatingPointType and - result.(IRFloatingPointType).getByteSize() = type.getSize() + exists(FloatingPointType floatType, IRFloatingPointType irFloatType | + floatType = unspecifiedType and + irFloatType = result and + irFloatType.getByteSize() = floatType.getSize() and + irFloatType.getBase() = floatType.getBase() and + irFloatType.getDomain() = floatType.getDomain() + ) or isPointerIshType(unspecifiedType) and result.(IRAddressType).getByteSize() = getTypeSize(type) or @@ -438,15 +449,37 @@ CppPRValueType getCanonicalUnsignedIntegerType(int byteSize) { } /** - * Gets the `CppType` that is the canonical type for an `IRFloatingPointType` with the specified - * `byteSize`. + * Gets the sort priority of a `RealNumberType` base on its precision. */ -CppPRValueType getCanonicalFloatingPointType(int byteSize) { +private int getPrecisionPriority(RealNumberType type) { + // Prefer `double`, `float`, `long double` in that order. + if type instanceof DoubleType + then result = 4 + else + if type instanceof FloatType + then result = 3 + else + if type instanceof LongDoubleType + then result = 2 + else + // If we get this far, prefer non-extended-precision types. + if not type.isExtendedPrecision() + then result = 1 + else result = 0 +} + +/** + * Gets the `CppType` that is the canonical type for an `IRFloatingPointType` with the specified + * size, base, and type domain. + */ +CppPRValueType getCanonicalFloatingPointType(int byteSize, int base, TypeDomain domain) { result = TPRValueType(max(FloatingPointType type | - type.getSize() = byteSize + type.getSize() = byteSize and + type.getBase() = base and + type.getDomain() = domain | - type order by type.toString() desc + type order by getPrecisionPriority(type.getRealType()), type.toString() desc )) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 6e88e711711..f047d6c4753 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -9,6 +9,14 @@ class LanguageType = CppType; class OpaqueTypeTag = Cpp::Type; +class TypeDomain = Cpp::TypeDomain; + +class RealDomain = Cpp::RealDomain; + +class ComplexDomain = Cpp::ComplexDomain; + +class ImaginaryDomain = Cpp::ImaginaryDomain; + class Function = Cpp::Function; class Location = Cpp::Location; diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll index 53c15663796..6b2b4c918af 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/IRUtilities.qll @@ -23,17 +23,20 @@ Type getVariableType(Variable v) { then result = getDecayedType(declaredType) or - not exists(getDecayedType(declaredType)) and result = declaredType + not exists(getDecayedType(declaredType)) and result = v.getType() else if declaredType instanceof ArrayType and not declaredType.(ArrayType).hasArraySize() then - result = v.getInitializer().getExpr().getUnspecifiedType() + result = v.getInitializer().getExpr().getType() or - not exists(v.getInitializer()) and result = declaredType - else result = declaredType + not exists(v.getInitializer()) and result = v.getType() + else result = v.getType() ) } +/** + * Holds if the database contains a `case` label with the specified minimum and maximum value. + */ predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) { minValue = switchCase.getExpr().getFullyConverted().getValue() and if exists(switchCase.getEndExpr()) diff --git a/cpp/ql/src/semmle/code/cpp/models/Models.qll b/cpp/ql/src/semmle/code/cpp/models/Models.qll index 4689cb1c7c8..f02d05be711 100644 --- a/cpp/ql/src/semmle/code/cpp/models/Models.qll +++ b/cpp/ql/src/semmle/code/cpp/models/Models.qll @@ -12,4 +12,5 @@ private import implementations.Strcat private import implementations.Strcpy private import implementations.Strdup private import implementations.Strftime +private import implementations.StdString private import implementations.Swap diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll index e2f34fe03cc..f6f7ab279a6 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Allocation.qll @@ -1,3 +1,9 @@ +/** + * Provides implementation classes modelling various methods of allocation + * (`malloc`, `new` etc). See `semmle.code.cpp.models.interfaces.Allocation` + * for usage information. + */ + import semmle.code.cpp.models.interfaces.Allocation /** @@ -215,6 +221,40 @@ class SizelessAllocationFunction extends AllocationFunction { } } +/** + * An `operator new` or `operator new[]` function that may be associated with `new` or + * `new[]` expressions. Note that `new` and `new[]` are not function calls, but these + * functions may also be called directly. + */ +class OperatorNewAllocationFunction extends AllocationFunction { + OperatorNewAllocationFunction() { + exists(string name | + hasGlobalName(name) and + ( + // operator new(bytes, ...) + name = "operator new" + or + // operator new[](bytes, ...) + name = "operator new[]" + ) + ) + } + + override int getSizeArg() { result = 0 } + + override predicate requiresDealloc() { not exists(getPlacementArgument()) } + + /** + * Gets the position of the placement pointer if this is a placement + * `operator new` function. + */ + int getPlacementArgument() { + getNumberOfParameters() = 2 and + getParameter(1).getType() instanceof VoidPointerType and + result = 1 + } +} + /** * An allocation expression that is a function call, such as call to `malloc`. */ @@ -227,7 +267,9 @@ class CallAllocationExpr extends AllocationExpr, FunctionCall { not ( exists(target.getReallocPtrArg()) and getArgument(target.getSizeArg()).getValue().toInt() = 0 - ) + ) and + // these are modelled directly (and more accurately), avoid duplication + not exists(NewOrNewArrayExpr new | new.getAllocatorCall() = this) } override Expr getSizeExpr() { result = getArgument(target.getSizeArg()) } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll index 83309855e18..980645df031 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Deallocation.qll @@ -1,4 +1,10 @@ -import semmle.code.cpp.models.interfaces.Allocation +/** + * Provides implementation classes modelling various methods of deallocation + * (`free`, `delete` etc). See `semmle.code.cpp.models.interfaces.Deallocation` + * for usage information. + */ + +import semmle.code.cpp.models.interfaces.Deallocation /** * A deallocation function such as `free`. @@ -79,6 +85,28 @@ class StandardDeallocationFunction extends DeallocationFunction { override int getFreedArg() { result = freedArg } } +/** + * An `operator delete` or `operator delete[]` function that may be associated + * with `delete` or `delete[]` expressions. Note that `delete` and `delete[]` + * are not function calls, but these functions may also be called directly. + */ +class OperatorDeleteDeallocationFunction extends DeallocationFunction { + OperatorDeleteDeallocationFunction() { + exists(string name | + hasGlobalName(name) and + ( + // operator delete(pointer, ...) + name = "operator delete" + or + // operator delete[](pointer, ...) + name = "operator delete[]" + ) + ) + } + + override int getFreedArg() { result = 0 } +} + /** * An deallocation expression that is a function call, such as call to `free`. */ diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll new file mode 100644 index 00000000000..80fe85e9f13 --- /dev/null +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/StdString.qll @@ -0,0 +1,27 @@ +import semmle.code.cpp.models.interfaces.Taint + +/** + * The `std::basic_string` constructor(s). + */ +class StdStringConstructor extends TaintFunction { + StdStringConstructor() { this.hasQualifiedName("std", "basic_string", "basic_string") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from any constructor argument to return value + input.isParameter(_) and + output.isReturnValue() + } +} + +/** + * The standard function `std::string.c_str`. + */ +class StdStringCStr extends TaintFunction { + StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") } + + override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { + // flow from string itself (qualifier) to return value + input.isQualifierObject() and + output.isReturnValue() + } +} diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll index d56ebf10bbc..d44b28f041d 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcat.qll @@ -1,11 +1,12 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.SideEffect /** * The standard function `strcat` and its wide, sized, and Microsoft variants. */ -class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction { +class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction { StrcatFunction() { exists(string name | name = getName() | name = "strcat" or // strcat(dst, src) @@ -56,4 +57,19 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction { override predicate hasArrayWithNullTerminator(int param) { param = 1 } override predicate hasArrayWithUnknownSize(int param) { param = 0 } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and + buffer = true and + mustWrite = false + } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + (i = 0 or i = 1) and + buffer = true + } } diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll index d4d7bcf2881..c7f0898f358 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Strcpy.qll @@ -1,11 +1,12 @@ import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.DataFlow import semmle.code.cpp.models.interfaces.Taint +import semmle.code.cpp.models.interfaces.SideEffect /** * The standard function `strcpy` and its wide, sized, and Microsoft variants. */ -class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { +class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction { StrcpyFunction() { this.hasName("strcpy") or this.hasName("_mbscpy") or @@ -74,4 +75,23 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction { output.isReturnValueDeref() ) } + + override predicate hasOnlySpecificReadSideEffects() { any() } + + override predicate hasOnlySpecificWriteSideEffects() { any() } + + override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) { + i = 0 and + buffer = true and + mustWrite = false + } + + override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) { + i = 1 and + buffer = true + } + + override ParameterIndex getParameterSizeIndex(ParameterIndex i) { + hasArrayWithVariableSize(i, result) + } } diff --git a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll index 8047bc384b2..23dda0ddb1e 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FunctionWithWrappers.qll @@ -19,7 +19,7 @@ private predicate wrapperFunctionStep( ) { not target.isVirtual() and not source.isVirtual() and - source.isDefined() and + source.hasDefinition() and exists(Call call, Expr arg, Parameter sourceParam | // there is a 'call' to 'target' with argument 'arg' at index 'targetParamIndex' target = resolveCall(call) and diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll index 3a37b43b319..a24820b277f 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -328,14 +328,24 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { } /** - * A variable that has any kind of upper-bound check anywhere in the program + * A variable that has any kind of upper-bound check anywhere in the program. This is + * biased towards being inclusive because there are a lot of valid ways of doing an + * upper bounds checks if we don't consider where it occurs, for example: + * ``` + * if (x < 10) { sink(x); } + * + * if (10 > y) { sink(y); } + * + * if (z > 10) { z = 10; } + * sink(z); + * ``` */ private predicate hasUpperBoundsCheck(Variable var) { exists(RelationalOperation oper, VariableAccess access | - oper.getLeftOperand() = access and + oper.getAnOperand() = access and access.getTarget() = var and // Comparing to 0 is not an upper bound check - not oper.getRightOperand().getValue() = "0" + not oper.getAnOperand().getValue() = "0" ) } diff --git a/cpp/ql/test/library-tests/allocators/allocators.cpp b/cpp/ql/test/library-tests/allocators/allocators.cpp index 6571245f5fc..92241b9c9e3 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.cpp +++ b/cpp/ql/test/library-tests/allocators/allocators.cpp @@ -143,3 +143,9 @@ void multidimensionalNew(int x, int y) { auto p2 = new char[20][20]; auto p3 = new char[x][30][30]; } + +void directOperatorCall() { + void *ptr; + ptr = operator new(sizeof(int)); + operator delete(ptr); +} diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index ee67a413692..2f9b4413e8c 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -1,28 +1,28 @@ newExprs -| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | -| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | -| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | -| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | -| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | -| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | -| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | -| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | -| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | -| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | -| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | +| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | +| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | | +| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | +| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | | +| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | | +| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | | +| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | | +| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | | +| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | +| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | & ... | +| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | | newArrayExprs -| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | -| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | -| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | -| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | -| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | -| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | -| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | -| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | -| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | -| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | -| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | -| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | +| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | | +| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | | +| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | | +| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | | +| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | | +| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | | +| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | | +| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | buf | +| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | | +| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | | +| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | | +| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | | newExprDeallocators | allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | | @@ -46,3 +46,65 @@ deleteArrayExprs | allocators.cpp:81:3:81:45 | delete[] | Overaligned | operator delete[](void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | | allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | | allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | +allocationFunctions +| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| allocators.cpp:121:7:121:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 | +| allocators.cpp:122:7:122:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 | +| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc | +| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc | +| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc | +allocationExprs +| allocators.cpp:49:3:49:9 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:50:3:50:15 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:51:3:51:11 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:52:3:52:14 | new | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:53:3:53:27 | new | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:54:3:54:17 | new | getSizeBytes = 256, requiresDealloc | +| allocators.cpp:55:3:55:25 | new | getSizeBytes = 256, requiresDealloc | +| allocators.cpp:68:3:68:12 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | +| allocators.cpp:69:3:69:18 | new[] | getSizeExpr = n, getSizeMult = 4, requiresDealloc | +| allocators.cpp:70:3:70:15 | new[] | getSizeExpr = n, getSizeMult = 8, requiresDealloc | +| allocators.cpp:71:3:71:20 | new[] | getSizeExpr = n, getSizeMult = 256, requiresDealloc | +| allocators.cpp:72:3:72:16 | new[] | getSizeBytes = 80, requiresDealloc | +| allocators.cpp:107:3:107:18 | new | getSizeBytes = 1, requiresDealloc | +| allocators.cpp:108:3:108:19 | new[] | getSizeExpr = n, getSizeMult = 1, requiresDealloc | +| allocators.cpp:109:3:109:35 | new | getSizeBytes = 128, requiresDealloc | +| allocators.cpp:110:3:110:37 | new[] | getSizeBytes = 1280, requiresDealloc | +| allocators.cpp:129:3:129:21 | new | getSizeBytes = 4 | +| allocators.cpp:132:3:132:17 | new[] | getSizeBytes = 4 | +| allocators.cpp:135:3:135:26 | new | getSizeBytes = 4, requiresDealloc | +| allocators.cpp:136:3:136:26 | new[] | getSizeBytes = 8, requiresDealloc | +| allocators.cpp:142:13:142:27 | new[] | getSizeExpr = x, getSizeMult = 10, requiresDealloc | +| allocators.cpp:143:13:143:28 | new[] | getSizeBytes = 400, requiresDealloc | +| allocators.cpp:144:13:144:31 | new[] | getSizeExpr = x, getSizeMult = 900, requiresDealloc | +| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc | +deallocationFunctions +| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 | +| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 | +| allocators.cpp:13:6:13:20 | operator delete | getFreedArg = 0 | +| allocators.cpp:14:6:14:22 | operator delete[] | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 | +| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 | +deallocationExprs +| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 | +| allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 | +| allocators.cpp:61:3:61:44 | delete | getFreedExpr = 0 | +| allocators.cpp:62:3:62:43 | delete | getFreedExpr = 0 | +| allocators.cpp:63:3:63:47 | delete | getFreedExpr = 0 | +| allocators.cpp:64:3:64:44 | delete | getFreedExpr = 0 | +| allocators.cpp:78:3:78:37 | delete[] | getFreedExpr = 0 | +| allocators.cpp:79:3:79:40 | delete[] | getFreedExpr = 0 | +| allocators.cpp:80:3:80:46 | delete[] | getFreedExpr = 0 | +| allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 | +| allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 | +| allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer | +| allocators.cpp:150:2:150:16 | call to operator delete | getFreedExpr = ptr | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index 37603f77a3e..e45667fbf01 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,6 +1,9 @@ import default +import semmle.code.cpp.models.implementations.Allocation -query predicate newExprs(NewExpr expr, string type, string sig, int size, int alignment, string form) { +query predicate newExprs( + NewExpr expr, string type, string sig, int size, int alignment, string form, string placement +) { exists(Function allocator, Type allocatedType | expr.getAllocator() = allocator and sig = allocator.getFullSignature() and @@ -8,13 +11,16 @@ query predicate newExprs(NewExpr expr, string type, string sig, int size, int al type = allocatedType.toString() and size = allocatedType.getSize() and alignment = allocatedType.getAlignment() and - if expr.hasAlignedAllocation() then form = "aligned" else form = "" + (if expr.hasAlignedAllocation() then form = "aligned" else form = "") and + if exists(expr.getPlacementPointer()) + then placement = expr.getPlacementPointer().toString() + else placement = "" ) } query predicate newArrayExprs( NewArrayExpr expr, string t1, string t2, string sig, int size, int alignment, string form, - string extents + string extents, string placement ) { exists(Function allocator, Type arrayType, Type elementType | expr.getAllocator() = allocator and @@ -26,7 +32,10 @@ query predicate newArrayExprs( size = elementType.getSize() and alignment = elementType.getAlignment() and (if expr.hasAlignedAllocation() then form = "aligned" else form = "") and - extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") + extents = concat(Expr e | e = expr.getExtent() | e.toString(), ", ") and + if exists(expr.getPlacementPointer()) + then placement = expr.getPlacementPointer().toString() + else placement = "" ) } @@ -101,3 +110,54 @@ query predicate deleteArrayExprs( ) ) } + +string describeAllocationFunction(AllocationFunction f) { + result = "getSizeArg = " + f.getSizeArg().toString() + or + result = "getSizeMult = " + f.getSizeMult().toString() + or + result = "getReallocPtrArg = " + f.getReallocPtrArg().toString() + or + f.requiresDealloc() and + result = "requiresDealloc" + or + result = + "getPlacementArgument = " + f.(OperatorNewAllocationFunction).getPlacementArgument().toString() +} + +query predicate allocationFunctions(AllocationFunction f, string descr) { + descr = concat(describeAllocationFunction(f), ", ") +} + +string describeAllocationExpr(AllocationExpr e) { + result = "getSizeExpr = " + e.getSizeExpr().toString() + or + result = "getSizeMult = " + e.getSizeMult().toString() + or + result = "getSizeBytes = " + e.getSizeBytes().toString() + or + result = "getReallocPtr = " + e.getReallocPtr().toString() + or + e.requiresDealloc() and + result = "requiresDealloc" +} + +query predicate allocationExprs(AllocationExpr e, string descr) { + descr = concat(describeAllocationExpr(e), ", ") +} + +string describeDeallocationFunction(DeallocationFunction f) { + result = "getFreedArg = " + f.getFreedArg().toString() +} + +query predicate deallocationFunctions(DeallocationFunction f, string descr) { + descr = concat(describeDeallocationFunction(f), ", ") +} + +string describeDeallocationExpr(DeallocationExpr e) { + result = "getFreedExpr = " + e.getFreedExpr().toString() +} + +query predicate deallocationExprs(DeallocationExpr e, string descr) { + descr = concat(describeDeallocationExpr(e), ", ") +} diff --git a/cpp/ql/test/library-tests/allocators/placement.expected b/cpp/ql/test/library-tests/allocators/placement.expected deleted file mode 100644 index 5755e349eb3..00000000000 --- a/cpp/ql/test/library-tests/allocators/placement.expected +++ /dev/null @@ -1,2 +0,0 @@ -| allocators.cpp:129:3:129:21 | new | allocators.cpp:129:7:129:13 | & ... | -| allocators.cpp:132:3:132:17 | new[] | allocators.cpp:132:7:132:9 | buf | diff --git a/cpp/ql/test/library-tests/allocators/placement.ql b/cpp/ql/test/library-tests/allocators/placement.ql deleted file mode 100644 index a632c3c5afe..00000000000 --- a/cpp/ql/test/library-tests/allocators/placement.ql +++ /dev/null @@ -1,4 +0,0 @@ -import cpp - -from NewOrNewArrayExpr new -select new, new.getPlacementPointer() as placement diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp index 02ae1e07154..25fbdba93c1 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp @@ -86,4 +86,14 @@ namespace std { void test_std_move() { sink(std::move(getenv("VAR"))); +} + +void flow_to_outparam(char ** ret, char *arg) { + *ret = arg; +} + +void test_outparams() { + char *p2 = nullptr; + flow_to_outparam(&p2, getenv("VAR")); + sink(p2); // tainted } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected index 99e970c9b40..4f98b1bead0 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected @@ -101,6 +101,14 @@ | defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:23 | call to getenv | | defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:30 | (reference to) | | defaulttainttracking.cpp:88:18:88:23 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:91:42:91:44 | arg | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:92:12:92:14 | arg | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:96:11:96:12 | p2 | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:97:27:97:32 | call to getenv | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | (const char *)... | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | p2 | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | | globals.cpp:5:20:5:25 | call to getenv | globals.cpp:2:17:2:25 | sinkParam | | globals.cpp:5:20:5:25 | call to getenv | globals.cpp:5:12:5:16 | local | | globals.cpp:5:20:5:25 | call to getenv | globals.cpp:5:20:5:25 | call to getenv | diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected index 335cca91c33..858965a069b 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected @@ -15,6 +15,14 @@ | defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:32 | (reference dereference) | IR only | | defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:30 | (reference to) | IR only | | defaulttainttracking.cpp:88:18:88:23 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | IR only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | IR only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:91:31:91:33 | ret | AST only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:92:5:92:8 | * ... | AST only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:92:6:92:8 | ret | AST only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:96:11:96:12 | p2 | IR only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | (const char *)... | IR only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | defaulttainttracking.cpp:98:10:98:11 | p2 | IR only | +| defaulttainttracking.cpp:97:27:97:32 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | IR only | | globals.cpp:13:15:13:20 | call to getenv | globals.cpp:13:5:13:11 | global1 | AST only | | globals.cpp:23:15:23:20 | call to getenv | globals.cpp:23:5:23:11 | global2 | AST only | | test_diff.cpp:104:12:104:15 | argv | test_diff.cpp:104:11:104:20 | (...) | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected new file mode 100644 index 00000000000..10dc6d411b7 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -0,0 +1,31 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| dispatch.cpp:60:18:60:29 | call to Bottom | Node should have one location but has 2. | +| dispatch.cpp:61:18:61:29 | call to Middle | Node should have one location but has 2. | +| dispatch.cpp:65:10:65:21 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Bottom | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Middle | Node should have one location but has 2. | +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| dispatch.cpp:78:23:78:39 | * ... | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:18:7:18:7 | a | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:25:2:25:2 | b | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:32:2:32:2 | c | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:38:2:38:2 | d | ArgumentNode is missing PostUpdateNode. | +| lambdas.cpp:45:2:45:2 | e | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..3940c1e8389 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -0,0 +1,38 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| BarrierGuard.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| acrossLinkTargets.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| clang.cpp:4:11:4:13 | p#0 | Node should have one location but has 6. | +| clang.cpp:4:27:4:35 | p#0 | Node should have one location but has 2. | +| clang.cpp:4:51:4:53 | p#0 | Node should have one location but has 2. | +| dispatch.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| globals.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| test.cpp:2:11:2:13 | p#0 | Node should have one location but has 6. | +| test.cpp:2:27:2:35 | p#0 | Node should have one location but has 2. | +| test.cpp:2:51:2:53 | p#0 | Node should have one location but has 2. | +missingLocation +| Nodes without location: 4 | +uniqueNodeToString +| lambdas.cpp:2:6:2:9 | (no string representation) | Node should have one toString but has 0. | +missingToString +| Nodes without toString: 1 | +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +| ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. | +| ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. | +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index 6c445fb76c1..666edf7a177 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -460,3 +460,13 @@ void throughStmtExpr(int source1, int clean1) { }); sink(local); // tainted } + +void intOutparamSource(int *p) { + *p = source(); +} + +void viaOutparam() { + int x = 0; + intOutparamSource(&x); + sink(x); // tainted [FALSE NEGATIVE] +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 71630f892f5..9bad6e02bcc 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -31,10 +31,6 @@ | ref.cpp:53:17:53:18 | ref.cpp:62:10:62:11 | AST only | | ref.cpp:53:21:53:22 | ref.cpp:65:10:65:11 | AST only | | ref.cpp:55:23:55:28 | ref.cpp:56:10:56:11 | AST only | -| ref.cpp:94:15:94:20 | ref.cpp:129:13:129:15 | AST only | -| ref.cpp:109:15:109:20 | ref.cpp:132:13:132:15 | AST only | -| ref.cpp:122:23:122:28 | ref.cpp:123:13:123:15 | AST only | -| ref.cpp:125:19:125:24 | ref.cpp:126:13:126:15 | AST only | | test.cpp:75:7:75:8 | test.cpp:76:8:76:9 | AST only | | test.cpp:83:7:83:8 | test.cpp:84:8:84:18 | AST only | | test.cpp:83:7:83:8 | test.cpp:86:8:86:9 | AST only | @@ -45,9 +41,6 @@ | test.cpp:359:13:359:18 | test.cpp:365:10:365:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:369:10:369:14 | AST only | | test.cpp:373:13:373:18 | test.cpp:375:10:375:14 | AST only | -| test.cpp:382:48:382:54 | test.cpp:385:8:385:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:392:8:392:10 | AST only | -| test.cpp:388:53:388:59 | test.cpp:394:10:394:12 | AST only | | test.cpp:399:7:399:9 | test.cpp:401:8:401:10 | AST only | | test.cpp:405:7:405:9 | test.cpp:408:8:408:10 | AST only | | test.cpp:416:7:416:11 | test.cpp:418:8:418:12 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 275cbabc075..35068c56232 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -39,6 +39,10 @@ | globals.cpp:12:10:12:24 | flowTestGlobal1 | globals.cpp:13:23:13:28 | call to source | | globals.cpp:19:10:19:24 | flowTestGlobal2 | globals.cpp:23:23:23:28 | call to source | | lambdas.cpp:35:8:35:8 | a | lambdas.cpp:8:10:8:15 | call to source | +| ref.cpp:123:13:123:15 | val | ref.cpp:122:23:122:28 | call to source | +| ref.cpp:126:13:126:15 | val | ref.cpp:125:19:125:24 | call to source | +| ref.cpp:129:13:129:15 | val | ref.cpp:94:15:94:20 | call to source | +| ref.cpp:132:13:132:15 | val | ref.cpp:109:15:109:20 | call to source | | test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source | | test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source | @@ -61,6 +65,9 @@ | test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | | test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | | test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | +| test.cpp:385:8:385:10 | tmp | test.cpp:382:48:382:54 | source1 | +| test.cpp:392:8:392:10 | tmp | test.cpp:388:53:388:59 | source1 | +| test.cpp:394:10:394:12 | tmp | test.cpp:388:53:388:59 | source1 | | test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | | test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | | true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected new file mode 100644 index 00000000000..cdf03b90508 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -0,0 +1,58 @@ +uniqueEnclosingCallable +| C.cpp:37:24:37:33 | 0 | Node should have one enclosing callable but has 0. | +| C.cpp:37:24:37:33 | new | Node should have one enclosing callable but has 0. | +uniqueTypeBound +| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type bound but has 0. | +| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type bound but has 0. | +uniqueTypeRepr +| complex.cpp:22:11:22:17 | constructor init of field f [post-this] | Node should have one type representation but has 0. | +| complex.cpp:22:11:22:17 | constructor init of field f [pre-this] | Node should have one type representation but has 0. | +uniqueNodeLocation +| A.cpp:38:7:38:8 | call to C | Node should have one location but has 2. | +| A.cpp:39:7:39:8 | call to C | Node should have one location but has 2. | +| A.cpp:41:15:41:21 | call to C | Node should have one location but has 2. | +| A.cpp:47:12:47:18 | call to C | Node should have one location but has 2. | +| A.cpp:57:17:57:23 | call to C | Node should have one location but has 2. | +| A.cpp:64:21:64:28 | call to C2 | Node should have one location but has 2. | +| A.cpp:73:25:73:32 | call to C2 | Node should have one location but has 2. | +| A.cpp:126:12:126:18 | call to C | Node should have one location but has 2. | +| A.cpp:142:14:142:20 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C2 | Node should have one location but has 2. | +| file://:0:0:0:0 | call to C2 | Node should have one location but has 2. | +missingLocation +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| A.cpp:41:15:41:21 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:55:12:55:19 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:57:17:57:23 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:64:21:64:28 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:73:25:73:32 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:126:12:126:18 | new | ArgumentNode is missing PostUpdateNode. | +| A.cpp:160:32:160:59 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:29:24:29:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:36:24:36:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:43:24:43:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:50:24:50:40 | new | ArgumentNode is missing PostUpdateNode. | +| D.cpp:57:25:57:41 | new | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:51:8:51:8 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:57:8:57:8 | s | ArgumentNode is missing PostUpdateNode. | +| by_reference.cpp:63:8:63:8 | s | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..1714355138c --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -0,0 +1,26 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| D.cpp:1:17:1:17 | o | Node should have one location but has 2. | +| by_reference.cpp:1:17:1:17 | o | Node should have one location but has 2. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +missingLocation +| Nodes without location: 4 | +uniqueNodeToString +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected new file mode 100644 index 00000000000..7a6432e29f3 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected @@ -0,0 +1,82 @@ +edges +| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] | +| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] | +| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store | +| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | +| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c | +| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] | +| A.cpp:154:13:154:13 | c | A.cpp:154:10:154:13 | (void *)... | +| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | +| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] | +| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store | +| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | +| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] | +| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store | +| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] | +| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:26:19:26:20 | Chi [m1] | +| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | +| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] | +| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] | +| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store | +| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | +| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | +| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | +nodes +| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] | +| A.cpp:142:7:142:20 | Store | semmle.label | Store | +| A.cpp:142:14:142:20 | new | semmle.label | new | +| A.cpp:151:18:151:18 | Chi [c] | semmle.label | Chi [c] | +| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] | +| A.cpp:154:10:154:13 | (void *)... | semmle.label | (void *)... | +| A.cpp:154:13:154:13 | c | semmle.label | c | +| A.cpp:154:13:154:13 | c | semmle.label | c | +| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store | +| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store | +| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] | +| aliasing.cpp:26:19:26:20 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] | +| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | +| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | +| aliasing.cpp:37:13:37:22 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 | +| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 | +| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] | +| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store | +| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] | +| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 | +| aliasing.cpp:79:11:79:20 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 | +| aliasing.cpp:86:10:86:19 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 | +| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | +| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | +| struct_init.c:22:11:22:11 | a | semmle.label | a | +| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | +| struct_init.c:31:23:31:23 | a | semmle.label | a | +#select +| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input | +| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input | +| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input | call to user_input | +| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input | call to user_input | +| aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input | +| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input | call to user_input | +| aliasing.cpp:87:12:87:13 | m1 | aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 | m1 flows from $@ | aliasing.cpp:86:10:86:19 | call to user_input | call to user_input | +| aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input | +| struct_init.c:22:11:22:11 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input | +| struct_init.c:31:23:31:23 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql new file mode 100644 index 00000000000..098c6b6bd27 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-flow.ql @@ -0,0 +1,46 @@ +/** + * @kind path-problem + */ + +import semmle.code.cpp.ir.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon +import semmle.code.cpp.ir.IR +import DataFlow::PathGraph +import cpp + +class Conf extends DataFlow::Configuration { + Conf() { this = "FieldFlowConf" } + + override predicate isSource(Node src) { + src.asExpr() instanceof NewExpr + or + src.asExpr().(Call).getTarget().hasName("user_input") + or + exists(FunctionCall fc | + fc.getAnArgument() = src.asDefiningArgument() and + fc.getTarget().hasName("argument_source") + ) + } + + override predicate isSink(Node sink) { + exists(Call c | + c.getTarget().hasName("sink") and + c.getAnArgument() = sink.asExpr() + ) + } + + override predicate isAdditionalFlowStep(Node a, Node b) { + b.asPartialDefinition() = + any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr()) + .getQualifier() + or + b.asExpr().(AddressOfExpr).getOperand() = a.asExpr() + } +} + +from DataFlow::PathNode src, DataFlow::PathNode sink, Conf conf +where conf.hasFlowPath(src, sink) +select sink, src, sink, sink + " flows from $@", src, src.toString() diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected index f4a9288036d..cdea135e301 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted.expected @@ -73,3 +73,18 @@ | test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | | | test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected index 8cc64a4c9bc..26441b08ba4 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected @@ -14,3 +14,6 @@ | test.cpp:100:12:100:15 | call to gets | test.cpp:100:2:100:8 | pointer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:97:7:97:12 | buffer | AST only | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | IR only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:108:8:108:11 | copy | AST only | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:9:109:12 | copy | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected index c8cca156177..50c90bccb2b 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected @@ -57,3 +57,15 @@ | test.cpp:100:17:100:22 | buffer | test.cpp:93:18:93:18 | s | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | array to pointer conversion | | | test.cpp:100:17:100:22 | buffer | test.cpp:100:17:100:22 | buffer | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:8:24:8:25 | s1 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:11:36:11:37 | s2 | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:17:106:24 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:33 | call to getenv | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:106:28:106:46 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:2:109:7 | call to strcpy | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:109:15:109:22 | userName | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:6:111:27 | ! ... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:12 | call to strcmp | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:7:111:27 | (bool)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | (const char *)... | | +| test.cpp:106:28:106:33 | call to getenv | test.cpp:111:14:111:17 | copy | | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp index 5feea7d1e7b..f25f9eeb697 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/security-taint/test.cpp @@ -99,3 +99,16 @@ void test_gets() pointer = gets(buffer); } + +const char *alias_global_new; + +void newBuffer() { + const char *userName = getenv("USER_NAME"); + char *alias = new char[4096]; + char *copy = new char[4096]; + strcpy(copy, userName); + alias_global_new = alias; // to force a Chi node on all aliased memory + if (!strcmp(copy, "admin")) { // copy should be tainted + isAdmin = true; + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 648159b4944..ec88e5bc628 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -105,6 +105,63 @@ | format.cpp:130:23:130:23 | 0 | format.cpp:130:21:130:24 | {...} | TAINT | | format.cpp:131:39:131:45 | ref arg & ... | format.cpp:132:8:132:13 | buffer | | | format.cpp:131:40:131:45 | buffer | format.cpp:131:39:131:45 | & ... | | +| stl.cpp:67:12:67:17 | call to source | stl.cpp:71:7:71:7 | a | | +| stl.cpp:68:16:68:20 | 123 | stl.cpp:68:16:68:21 | call to basic_string | TAINT | +| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:72:7:72:7 | b | | +| stl.cpp:68:16:68:21 | call to basic_string | stl.cpp:74:7:74:7 | b | | +| stl.cpp:69:16:69:21 | call to source | stl.cpp:69:16:69:24 | call to basic_string | TAINT | +| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:73:7:73:7 | c | | +| stl.cpp:69:16:69:24 | call to basic_string | stl.cpp:75:7:75:7 | c | | +| stl.cpp:74:7:74:7 | b | stl.cpp:74:9:74:13 | call to c_str | TAINT | +| stl.cpp:75:7:75:7 | c | stl.cpp:75:9:75:13 | call to c_str | TAINT | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:83:2:83:4 | ss1 | | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:89:7:89:9 | ss1 | | +| stl.cpp:80:20:80:22 | call to basic_stringstream | stl.cpp:94:7:94:9 | ss1 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:84:2:84:4 | ss2 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:90:7:90:9 | ss2 | | +| stl.cpp:80:25:80:27 | call to basic_stringstream | stl.cpp:95:7:95:9 | ss2 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:85:2:85:4 | ss3 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:91:7:91:9 | ss3 | | +| stl.cpp:80:30:80:32 | call to basic_stringstream | stl.cpp:96:7:96:9 | ss3 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:86:2:86:4 | ss4 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:92:7:92:9 | ss4 | | +| stl.cpp:80:35:80:37 | call to basic_stringstream | stl.cpp:97:7:97:9 | ss4 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:87:2:87:4 | ss5 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:93:7:93:9 | ss5 | | +| stl.cpp:80:40:80:42 | call to basic_stringstream | stl.cpp:98:7:98:9 | ss5 | | +| stl.cpp:81:16:81:21 | call to source | stl.cpp:81:16:81:24 | call to basic_string | TAINT | +| stl.cpp:81:16:81:24 | call to basic_string | stl.cpp:87:9:87:9 | t | | +| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:89:7:89:9 | ss1 | | +| stl.cpp:83:2:83:4 | ref arg ss1 | stl.cpp:94:7:94:9 | ss1 | | +| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:90:7:90:9 | ss2 | | +| stl.cpp:84:2:84:4 | ref arg ss2 | stl.cpp:95:7:95:9 | ss2 | | +| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:91:7:91:9 | ss3 | | +| stl.cpp:85:2:85:4 | ref arg ss3 | stl.cpp:96:7:96:9 | ss3 | | +| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:92:7:92:9 | ss4 | | +| stl.cpp:86:2:86:4 | ref arg ss4 | stl.cpp:97:7:97:9 | ss4 | | +| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:93:7:93:9 | ss5 | | +| stl.cpp:87:2:87:4 | ref arg ss5 | stl.cpp:98:7:98:9 | ss5 | | +| stl.cpp:101:32:101:37 | source | stl.cpp:106:9:106:14 | source | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:105:2:105:4 | ss1 | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:108:7:108:9 | ss1 | | +| stl.cpp:103:20:103:22 | call to basic_stringstream | stl.cpp:110:7:110:9 | ss1 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:106:2:106:4 | ss2 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:109:7:109:9 | ss2 | | +| stl.cpp:103:25:103:27 | call to basic_stringstream | stl.cpp:111:7:111:9 | ss2 | | +| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:108:7:108:9 | ss1 | | +| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:110:7:110:9 | ss1 | | +| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:109:7:109:9 | ss2 | | +| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:111:7:111:9 | ss2 | | +| stl.cpp:124:16:124:28 | call to basic_string | stl.cpp:125:7:125:11 | path1 | | +| stl.cpp:124:17:124:26 | call to user_input | stl.cpp:124:16:124:28 | call to basic_string | TAINT | +| stl.cpp:125:7:125:11 | path1 | stl.cpp:125:13:125:17 | call to c_str | TAINT | +| stl.cpp:128:10:128:19 | call to user_input | stl.cpp:128:10:128:21 | call to basic_string | TAINT | +| stl.cpp:128:10:128:21 | call to basic_string | stl.cpp:128:2:128:21 | ... = ... | | +| stl.cpp:128:10:128:21 | call to basic_string | stl.cpp:129:7:129:11 | path2 | | +| stl.cpp:129:7:129:11 | path2 | stl.cpp:129:13:129:17 | call to c_str | TAINT | +| stl.cpp:131:15:131:24 | call to user_input | stl.cpp:131:15:131:27 | call to basic_string | TAINT | +| stl.cpp:131:15:131:27 | call to basic_string | stl.cpp:132:7:132:11 | path3 | | +| stl.cpp:132:7:132:11 | path3 | stl.cpp:132:13:132:17 | call to c_str | TAINT | | taint.cpp:4:27:4:33 | source1 | taint.cpp:6:13:6:19 | source1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:5:8:5:13 | clean1 | | | taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | | @@ -512,3 +569,20 @@ | taint.cpp:444:7:444:7 | d [post update] | taint.cpp:447:7:447:7 | d | | | taint.cpp:445:2:445:2 | d [post update] | taint.cpp:446:7:446:7 | d | | | taint.cpp:445:2:445:2 | d [post update] | taint.cpp:447:7:447:7 | d | | +| taint.cpp:452:16:452:16 | a | taint.cpp:454:10:454:10 | a | | +| taint.cpp:452:24:452:24 | b | taint.cpp:455:6:455:6 | b | | +| taint.cpp:454:10:454:10 | a | taint.cpp:456:6:456:6 | c | | +| taint.cpp:455:6:455:6 | b | taint.cpp:452:16:452:16 | a | | +| taint.cpp:455:6:455:6 | b | taint.cpp:455:2:455:6 | ... = ... | | +| taint.cpp:456:6:456:6 | c | taint.cpp:452:24:452:24 | b | | +| taint.cpp:456:6:456:6 | c | taint.cpp:456:2:456:6 | ... = ... | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:462:2:462:13 | ... = ... | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:465:7:465:7 | x | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:468:7:468:7 | x | | +| taint.cpp:462:6:462:11 | call to source | taint.cpp:470:7:470:7 | x | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:463:2:463:6 | ... = ... | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:466:7:466:7 | y | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:468:10:468:10 | y | | +| taint.cpp:463:6:463:6 | 0 | taint.cpp:471:7:471:7 | y | | +| taint.cpp:468:7:468:7 | ref arg x | taint.cpp:470:7:470:7 | x | | +| taint.cpp:468:10:468:10 | ref arg y | taint.cpp:471:7:471:7 | y | | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp new file mode 100644 index 00000000000..d92bb39d158 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/stl.cpp @@ -0,0 +1,133 @@ + +typedef unsigned long size_t; + +namespace std +{ + template struct char_traits; + + typedef size_t streamsize; + + template class allocator { + public: + allocator() throw(); + }; + + template, class Allocator = allocator > + class basic_string { + public: + explicit basic_string(const Allocator& a = Allocator()); + basic_string(const charT* s, const Allocator& a = Allocator()); + + const charT* c_str() const; + }; + + typedef basic_string string; + + template > + class basic_istream /*: virtual public basic_ios - not needed for this test */ { + public: + basic_istream& operator>>(int& n); + }; + + template > + class basic_ostream /*: virtual public basic_ios - not needed for this test */ { + public: + typedef charT char_type; + basic_ostream& write(const char_type* s, streamsize n); + + basic_ostream& operator<<(int n); + }; + + template basic_ostream& operator<<(basic_ostream&, const charT*); + template basic_ostream& operator<<(basic_ostream& os, const basic_string& str); + + template> + class basic_iostream : public basic_istream, public basic_ostream { + public: + }; + + template, class Allocator = allocator> + class basic_stringstream : public basic_iostream { + public: + explicit basic_stringstream(/*ios_base::openmode which = ios_base::out|ios_base::in - not needed for this test*/); + + basic_string str() const; + }; + + using stringstream = basic_stringstream; +} + +char *source(); +void sink(const char *s) {}; +void sink(const std::string &s) {}; +void sink(const std::stringstream &s) {}; + +void test_string() +{ + char *a = source(); + std::string b("123"); + std::string c(source()); + + sink(a); // tainted + sink(b); + sink(c); // tainted + sink(b.c_str()); + sink(c.c_str()); // tainted +} + +void test_stringstream() +{ + std::stringstream ss1, ss2, ss3, ss4, ss5; + std::string t(source()); + + ss1 << "1234"; + ss2 << source(); + ss3 << "123" << source(); + ss4 << source() << "456"; + ss5 << t; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss3); // tainted [NOT DETECTED] + sink(ss4); // tainted [NOT DETECTED] + sink(ss5); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] + sink(ss3.str()); // tainted [NOT DETECTED] + sink(ss4.str()); // tainted [NOT DETECTED] + sink(ss5.str()); // tainted [NOT DETECTED] +} + +void test_stringstream_int(int source) +{ + std::stringstream ss1, ss2; + + ss1 << 1234; + ss2 << source; + + sink(ss1); + sink(ss2); // tainted [NOT DETECTED] + sink(ss1.str()); + sink(ss2.str()); // tainted [NOT DETECTED] +} + +using namespace std; + +char *user_input() { + return source(); +} + +void sink(const char *filename, const char *mode); + +void test_strings2() +{ + string path1 = user_input(); + sink(path1.c_str(), "r"); // tainted + + string path2; + path2 = user_input(); + sink(path2.c_str(), "r"); // tainted + + string path3(user_input()); + sink(path3.c_str(), "r"); // tainted +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 3fff2fd7229..5d8327017fa 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -195,7 +195,7 @@ void test_memcpy(int *source) { sink(x); } -// --- swap --- +// --- std::swap --- namespace std { template constexpr void swap(T& a, T& b); @@ -446,3 +446,27 @@ void test_qualifiers() sink(d); // tainted sink(d.getString()); // tainted } + +// --- non-standard swap --- + +void swop(int &a, int &b) +{ + int c = a; + a = b; + b = c; +} + +void test_swop() { + int x, y; + + x = source(); + y = 0; + + sink(x); // tainted + sink(y); // clean + + swop(x, y); + + sink(x); // clean [FALSE POSITIVE] + sink(y); // tainted +} diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected index 46146094e53..59193d81722 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected @@ -8,6 +8,12 @@ | format.cpp:96:8:96:13 | buffer | format.cpp:95:30:95:43 | call to source | | format.cpp:101:8:101:13 | buffer | format.cpp:100:31:100:45 | call to source | | format.cpp:106:8:106:14 | wbuffer | format.cpp:105:38:105:52 | call to source | +| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | +| stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | call to source | +| stl.cpp:75:9:75:13 | call to c_str | stl.cpp:69:16:69:21 | call to source | +| stl.cpp:125:13:125:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | +| stl.cpp:129:13:129:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | +| stl.cpp:132:13:132:17 | call to c_str | stl.cpp:117:10:117:15 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | @@ -58,3 +64,6 @@ | taint.cpp:439:10:439:18 | call to getMember | taint.cpp:437:15:437:20 | call to source | | taint.cpp:446:7:446:7 | d | taint.cpp:445:14:445:28 | call to source | | taint.cpp:447:9:447:17 | call to getString | taint.cpp:445:14:445:28 | call to source | +| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source | +| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source | +| taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 7680193da16..3be23cbcc40 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -8,6 +8,11 @@ | format.cpp:96:8:96:13 | format.cpp:95:30:95:43 | AST only | | format.cpp:101:8:101:13 | format.cpp:100:31:100:45 | AST only | | format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | AST only | +| stl.cpp:73:7:73:7 | stl.cpp:69:16:69:21 | AST only | +| stl.cpp:75:9:75:13 | stl.cpp:69:16:69:21 | AST only | +| stl.cpp:125:13:125:17 | stl.cpp:117:10:117:15 | AST only | +| stl.cpp:129:13:129:17 | stl.cpp:117:10:117:15 | AST only | +| stl.cpp:132:13:132:17 | stl.cpp:117:10:117:15 | AST only | | taint.cpp:41:7:41:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:42:7:42:13 | taint.cpp:35:12:35:17 | AST only | | taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only | @@ -23,7 +28,6 @@ | taint.cpp:181:8:181:9 | taint.cpp:185:11:185:16 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:192:23:192:28 | AST only | | taint.cpp:195:7:195:7 | taint.cpp:193:6:193:6 | AST only | -| taint.cpp:216:7:216:7 | taint.cpp:207:6:207:11 | AST only | | taint.cpp:229:3:229:6 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:233:8:233:8 | taint.cpp:223:10:223:15 | AST only | | taint.cpp:236:3:236:6 | taint.cpp:223:10:223:15 | AST only | @@ -42,3 +46,4 @@ | taint.cpp:439:10:439:18 | taint.cpp:437:15:437:20 | AST only | | taint.cpp:446:7:446:7 | taint.cpp:445:14:445:28 | AST only | | taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only | +| taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index b38de345220..b44e17882e7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,3 +1,5 @@ +| stl.cpp:71:7:71:7 | (const char *)... | stl.cpp:67:12:67:17 | call to source | +| stl.cpp:71:7:71:7 | a | stl.cpp:67:12:67:17 | call to source | | taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | | taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | | taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | @@ -10,6 +12,7 @@ | taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | | taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | | taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source | +| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source | | taint.cpp:250:8:250:8 | a | taint.cpp:223:10:223:15 | call to source | | taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source | | taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source | @@ -20,3 +23,5 @@ | taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source | | taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source | | taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source | +| taint.cpp:465:7:465:7 | x | taint.cpp:462:6:462:11 | call to source | +| taint.cpp:470:7:470:7 | x | taint.cpp:462:6:462:11 | call to source | diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index abce5a6a19d..24b09161af3 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -234,6 +234,1487 @@ clang.cpp: # 6| 0: [VariableAccess] globalInt # 6| Type = [IntType] int # 6| ValueCategory = lvalue +complex.c: +# 1| [TopLevelFunction] void complex_literals() +# 1| params: +# 1| body: [Block] { ... } +# 2| 0: [DeclStmt] declaration +# 2| 0: [VariableDeclarationEntry] definition of cf +# 2| Type = [ArithmeticType] _Complex float +# 2| init: [Initializer] initializer for cf +# 2| expr: [CStyleCast] (_Complex float)... +# 2| Conversion = [FloatingPointConversion] floating point conversion +# 2| Type = [ArithmeticType] _Complex float +# 2| ValueCategory = prvalue +# 2| expr: [Literal] 2.0 +# 2| Type = [DoubleType] double +# 2| Value = [Literal] 2.0 +# 2| ValueCategory = prvalue +# 3| 1: [ExprStmt] ExprStmt +# 3| 0: [AssignExpr] ... = ... +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue +# 3| 0: [VariableAccess] cf +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = lvalue +# 3| 1: [CStyleCast] (_Complex float)... +# 3| Conversion = [FloatingPointConversion] floating point conversion +# 3| Type = [ArithmeticType] _Complex float +# 3| ValueCategory = prvalue +# 3| expr: [Literal] 1.0i +# 3| Type = [ArithmeticType] _Imaginary float +# 3| Value = [Literal] 1.0i +# 3| ValueCategory = prvalue +# 4| 2: [DeclStmt] declaration +# 4| 0: [VariableDeclarationEntry] definition of cd +# 4| Type = [ArithmeticType] _Complex double +# 4| init: [Initializer] initializer for cd +# 4| expr: [CStyleCast] (_Complex double)... +# 4| Conversion = [FloatingPointConversion] floating point conversion +# 4| Type = [ArithmeticType] _Complex double +# 4| ValueCategory = prvalue +# 4| expr: [Literal] 3.0 +# 4| Type = [DoubleType] double +# 4| Value = [Literal] 3.0 +# 4| ValueCategory = prvalue +# 5| 3: [ExprStmt] ExprStmt +# 5| 0: [AssignExpr] ... = ... +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = prvalue +# 5| 0: [VariableAccess] cd +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = lvalue +# 5| 1: [CStyleCast] (_Complex double)... +# 5| Conversion = [FloatingPointConversion] floating point conversion +# 5| Type = [ArithmeticType] _Complex double +# 5| ValueCategory = prvalue +# 5| expr: [Literal] 1.0i +# 5| Type = [ArithmeticType] _Imaginary float +# 5| Value = [Literal] 1.0i +# 5| ValueCategory = prvalue +# 6| 4: [DeclStmt] declaration +# 6| 0: [VariableDeclarationEntry] definition of cld +# 6| Type = [ArithmeticType] _Complex long double +# 6| init: [Initializer] initializer for cld +# 6| expr: [CStyleCast] (_Complex long double)... +# 6| Conversion = [FloatingPointConversion] floating point conversion +# 6| Type = [ArithmeticType] _Complex long double +# 6| ValueCategory = prvalue +# 6| expr: [Literal] 5.0 +# 6| Type = [DoubleType] double +# 6| Value = [Literal] 5.0 +# 6| ValueCategory = prvalue +# 7| 5: [ExprStmt] ExprStmt +# 7| 0: [AssignExpr] ... = ... +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = prvalue +# 7| 0: [VariableAccess] cld +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = lvalue +# 7| 1: [CStyleCast] (_Complex long double)... +# 7| Conversion = [FloatingPointConversion] floating point conversion +# 7| Type = [ArithmeticType] _Complex long double +# 7| ValueCategory = prvalue +# 7| expr: [Literal] 1.0i +# 7| Type = [ArithmeticType] _Imaginary float +# 7| Value = [Literal] 1.0i +# 7| ValueCategory = prvalue +# 9| 6: [DeclStmt] declaration +# 9| 0: [VariableDeclarationEntry] definition of jf +# 9| Type = [ArithmeticType] _Imaginary float +# 9| init: [Initializer] initializer for jf +# 9| expr: [Literal] 1.0i +# 9| Type = [ArithmeticType] _Imaginary float +# 9| Value = [Literal] 1.0i +# 9| ValueCategory = prvalue +# 10| 7: [DeclStmt] declaration +# 10| 0: [VariableDeclarationEntry] definition of jd +# 10| Type = [ArithmeticType] _Imaginary double +# 10| init: [Initializer] initializer for jd +# 10| expr: [CStyleCast] (_Imaginary double)... +# 10| Conversion = [FloatingPointConversion] floating point conversion +# 10| Type = [ArithmeticType] _Imaginary double +# 10| ValueCategory = prvalue +# 10| expr: [Literal] 1.0i +# 10| Type = [ArithmeticType] _Imaginary float +# 10| Value = [Literal] 1.0i +# 10| ValueCategory = prvalue +# 11| 8: [DeclStmt] declaration +# 11| 0: [VariableDeclarationEntry] definition of jld +# 11| Type = [ArithmeticType] _Imaginary long double +# 11| init: [Initializer] initializer for jld +# 11| expr: [CStyleCast] (_Imaginary long double)... +# 11| Conversion = [FloatingPointConversion] floating point conversion +# 11| Type = [ArithmeticType] _Imaginary long double +# 11| ValueCategory = prvalue +# 11| expr: [Literal] 1.0i +# 11| Type = [ArithmeticType] _Imaginary float +# 11| Value = [Literal] 1.0i +# 11| ValueCategory = prvalue +# 12| 9: [ReturnStmt] return ... +# 14| [TopLevelFunction] void complex_arithmetic() +# 14| params: +# 14| body: [Block] { ... } +# 15| 0: [DeclStmt] declaration +# 15| 0: [VariableDeclarationEntry] definition of f1 +# 15| Type = [FloatType] float +# 15| init: [Initializer] initializer for f1 +# 15| expr: [CStyleCast] (float)... +# 15| Conversion = [FloatingPointConversion] floating point conversion +# 15| Type = [FloatType] float +# 15| Value = [CStyleCast] 5.0 +# 15| ValueCategory = prvalue +# 15| expr: [Literal] 5.0 +# 15| Type = [DoubleType] double +# 15| Value = [Literal] 5.0 +# 15| ValueCategory = prvalue +# 16| 1: [DeclStmt] declaration +# 16| 0: [VariableDeclarationEntry] definition of f2 +# 16| Type = [FloatType] float +# 16| init: [Initializer] initializer for f2 +# 16| expr: [CStyleCast] (float)... +# 16| Conversion = [FloatingPointConversion] floating point conversion +# 16| Type = [FloatType] float +# 16| Value = [CStyleCast] 7.0 +# 16| ValueCategory = prvalue +# 16| expr: [Literal] 7.0 +# 16| Type = [DoubleType] double +# 16| Value = [Literal] 7.0 +# 16| ValueCategory = prvalue +# 17| 2: [DeclStmt] declaration +# 17| 0: [VariableDeclarationEntry] definition of f3 +# 17| Type = [FloatType] float +# 18| 3: [DeclStmt] declaration +# 18| 0: [VariableDeclarationEntry] definition of cf1 +# 18| Type = [ArithmeticType] _Complex float +# 18| init: [Initializer] initializer for cf1 +# 18| expr: [CStyleCast] (_Complex float)... +# 18| Conversion = [FloatingPointConversion] floating point conversion +# 18| Type = [ArithmeticType] _Complex float +# 18| ValueCategory = prvalue +# 18| expr: [Literal] 2.0 +# 18| Type = [DoubleType] double +# 18| Value = [Literal] 2.0 +# 18| ValueCategory = prvalue +# 19| 4: [DeclStmt] declaration +# 19| 0: [VariableDeclarationEntry] definition of cf2 +# 19| Type = [ArithmeticType] _Complex float +# 19| init: [Initializer] initializer for cf2 +# 19| expr: [CStyleCast] (_Complex float)... +# 19| Conversion = [FloatingPointConversion] floating point conversion +# 19| Type = [ArithmeticType] _Complex float +# 19| ValueCategory = prvalue +# 19| expr: [Literal] 1.0i +# 19| Type = [ArithmeticType] _Imaginary float +# 19| Value = [Literal] 1.0i +# 19| ValueCategory = prvalue +# 20| 5: [DeclStmt] declaration +# 20| 0: [VariableDeclarationEntry] definition of cf3 +# 20| Type = [ArithmeticType] _Complex float +# 21| 6: [DeclStmt] declaration +# 21| 0: [VariableDeclarationEntry] definition of jf1 +# 21| Type = [ArithmeticType] _Imaginary float +# 21| init: [Initializer] initializer for jf1 +# 21| expr: [Literal] 1.0i +# 21| Type = [ArithmeticType] _Imaginary float +# 21| Value = [Literal] 1.0i +# 21| ValueCategory = prvalue +# 22| 7: [DeclStmt] declaration +# 22| 0: [VariableDeclarationEntry] definition of jf2 +# 22| Type = [ArithmeticType] _Imaginary float +# 22| init: [Initializer] initializer for jf2 +# 22| expr: [Literal] 1.0i +# 22| Type = [ArithmeticType] _Imaginary float +# 22| Value = [Literal] 1.0i +# 22| ValueCategory = prvalue +# 23| 8: [DeclStmt] declaration +# 23| 0: [VariableDeclarationEntry] definition of jf3 +# 23| Type = [ArithmeticType] _Imaginary float +# 26| 9: [ExprStmt] ExprStmt +# 26| 0: [AssignExpr] ... = ... +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue +# 26| 0: [VariableAccess] cf3 +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = lvalue +# 26| 1: [UnaryPlusExpr] + ... +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue +# 26| 0: [VariableAccess] cf1 +# 26| Type = [ArithmeticType] _Complex float +# 26| ValueCategory = prvalue(load) +# 27| 10: [ExprStmt] ExprStmt +# 27| 0: [AssignExpr] ... = ... +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue +# 27| 0: [VariableAccess] cf3 +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = lvalue +# 27| 1: [UnaryMinusExpr] - ... +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue +# 27| 0: [VariableAccess] cf1 +# 27| Type = [ArithmeticType] _Complex float +# 27| ValueCategory = prvalue(load) +# 30| 11: [ExprStmt] ExprStmt +# 30| 0: [AssignExpr] ... = ... +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue +# 30| 0: [VariableAccess] cf3 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = lvalue +# 30| 1: [AddExpr] ... + ... +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue +# 30| 0: [VariableAccess] cf1 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue(load) +# 30| 1: [VariableAccess] cf2 +# 30| Type = [ArithmeticType] _Complex float +# 30| ValueCategory = prvalue(load) +# 31| 12: [ExprStmt] ExprStmt +# 31| 0: [AssignExpr] ... = ... +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue +# 31| 0: [VariableAccess] cf3 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = lvalue +# 31| 1: [SubExpr] ... - ... +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue +# 31| 0: [VariableAccess] cf1 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue(load) +# 31| 1: [VariableAccess] cf2 +# 31| Type = [ArithmeticType] _Complex float +# 31| ValueCategory = prvalue(load) +# 32| 13: [ExprStmt] ExprStmt +# 32| 0: [AssignExpr] ... = ... +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue +# 32| 0: [VariableAccess] cf3 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = lvalue +# 32| 1: [MulExpr] ... * ... +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue +# 32| 0: [VariableAccess] cf1 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue(load) +# 32| 1: [VariableAccess] cf2 +# 32| Type = [ArithmeticType] _Complex float +# 32| ValueCategory = prvalue(load) +# 33| 14: [ExprStmt] ExprStmt +# 33| 0: [AssignExpr] ... = ... +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue +# 33| 0: [VariableAccess] cf3 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = lvalue +# 33| 1: [DivExpr] ... / ... +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue +# 33| 0: [VariableAccess] cf1 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue(load) +# 33| 1: [VariableAccess] cf2 +# 33| Type = [ArithmeticType] _Complex float +# 33| ValueCategory = prvalue(load) +# 36| 15: [ExprStmt] ExprStmt +# 36| 0: [AssignExpr] ... = ... +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue +# 36| 0: [VariableAccess] jf3 +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = lvalue +# 36| 1: [UnaryPlusExpr] + ... +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue +# 36| 0: [VariableAccess] jf1 +# 36| Type = [ArithmeticType] _Imaginary float +# 36| ValueCategory = prvalue(load) +# 37| 16: [ExprStmt] ExprStmt +# 37| 0: [AssignExpr] ... = ... +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue +# 37| 0: [VariableAccess] jf3 +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = lvalue +# 37| 1: [UnaryMinusExpr] - ... +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue +# 37| 0: [VariableAccess] jf1 +# 37| Type = [ArithmeticType] _Imaginary float +# 37| ValueCategory = prvalue(load) +# 40| 17: [ExprStmt] ExprStmt +# 40| 0: [AssignExpr] ... = ... +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue +# 40| 0: [VariableAccess] jf3 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = lvalue +# 40| 1: [AddExpr] ... + ... +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue +# 40| 0: [VariableAccess] jf1 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue(load) +# 40| 1: [VariableAccess] jf2 +# 40| Type = [ArithmeticType] _Imaginary float +# 40| ValueCategory = prvalue(load) +# 41| 18: [ExprStmt] ExprStmt +# 41| 0: [AssignExpr] ... = ... +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue +# 41| 0: [VariableAccess] jf3 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = lvalue +# 41| 1: [SubExpr] ... - ... +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue +# 41| 0: [VariableAccess] jf1 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue(load) +# 41| 1: [VariableAccess] jf2 +# 41| Type = [ArithmeticType] _Imaginary float +# 41| ValueCategory = prvalue(load) +# 42| 19: [ExprStmt] ExprStmt +# 42| 0: [AssignExpr] ... = ... +# 42| Type = [FloatType] float +# 42| ValueCategory = prvalue +# 42| 0: [VariableAccess] f3 +# 42| Type = [FloatType] float +# 42| ValueCategory = lvalue +# 42| 1: [ImaginaryMulExpr] ... * ... +# 42| Type = [FloatType] float +# 42| ValueCategory = prvalue +# 42| 0: [VariableAccess] jf1 +# 42| Type = [ArithmeticType] _Imaginary float +# 42| ValueCategory = prvalue(load) +# 42| 1: [VariableAccess] jf2 +# 42| Type = [ArithmeticType] _Imaginary float +# 42| ValueCategory = prvalue(load) +# 43| 20: [ExprStmt] ExprStmt +# 43| 0: [AssignExpr] ... = ... +# 43| Type = [FloatType] float +# 43| ValueCategory = prvalue +# 43| 0: [VariableAccess] f3 +# 43| Type = [FloatType] float +# 43| ValueCategory = lvalue +# 43| 1: [DivExpr] ... / ... +# 43| Type = [FloatType] float +# 43| ValueCategory = prvalue +# 43| 0: [VariableAccess] jf1 +# 43| Type = [ArithmeticType] _Imaginary float +# 43| ValueCategory = prvalue(load) +# 43| 1: [VariableAccess] jf2 +# 43| Type = [ArithmeticType] _Imaginary float +# 43| ValueCategory = prvalue(load) +# 46| 21: [ExprStmt] ExprStmt +# 46| 0: [AssignExpr] ... = ... +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = prvalue +# 46| 0: [VariableAccess] cf3 +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = lvalue +# 46| 1: [ImaginaryRealAddExpr] ... + ... +# 46| Type = [ArithmeticType] _Complex float +# 46| ValueCategory = prvalue +# 46| 0: [VariableAccess] jf1 +# 46| Type = [ArithmeticType] _Imaginary float +# 46| ValueCategory = prvalue(load) +# 46| 1: [VariableAccess] f2 +# 46| Type = [FloatType] float +# 46| ValueCategory = prvalue(load) +# 47| 22: [ExprStmt] ExprStmt +# 47| 0: [AssignExpr] ... = ... +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = prvalue +# 47| 0: [VariableAccess] cf3 +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = lvalue +# 47| 1: [ImaginaryRealSubExpr] ... - ... +# 47| Type = [ArithmeticType] _Complex float +# 47| ValueCategory = prvalue +# 47| 0: [VariableAccess] jf1 +# 47| Type = [ArithmeticType] _Imaginary float +# 47| ValueCategory = prvalue(load) +# 47| 1: [VariableAccess] f2 +# 47| Type = [FloatType] float +# 47| ValueCategory = prvalue(load) +# 48| 23: [ExprStmt] ExprStmt +# 48| 0: [AssignExpr] ... = ... +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue +# 48| 0: [VariableAccess] jf3 +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = lvalue +# 48| 1: [MulExpr] ... * ... +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue +# 48| 0: [VariableAccess] jf1 +# 48| Type = [ArithmeticType] _Imaginary float +# 48| ValueCategory = prvalue(load) +# 48| 1: [VariableAccess] f2 +# 48| Type = [FloatType] float +# 48| ValueCategory = prvalue(load) +# 49| 24: [ExprStmt] ExprStmt +# 49| 0: [AssignExpr] ... = ... +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue +# 49| 0: [VariableAccess] jf3 +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = lvalue +# 49| 1: [DivExpr] ... / ... +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue +# 49| 0: [VariableAccess] jf1 +# 49| Type = [ArithmeticType] _Imaginary float +# 49| ValueCategory = prvalue(load) +# 49| 1: [VariableAccess] f2 +# 49| Type = [FloatType] float +# 49| ValueCategory = prvalue(load) +# 52| 25: [ExprStmt] ExprStmt +# 52| 0: [AssignExpr] ... = ... +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = prvalue +# 52| 0: [VariableAccess] cf3 +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = lvalue +# 52| 1: [RealImaginaryAddExpr] ... + ... +# 52| Type = [ArithmeticType] _Complex float +# 52| ValueCategory = prvalue +# 52| 0: [VariableAccess] f1 +# 52| Type = [FloatType] float +# 52| ValueCategory = prvalue(load) +# 52| 1: [VariableAccess] jf2 +# 52| Type = [ArithmeticType] _Imaginary float +# 52| ValueCategory = prvalue(load) +# 53| 26: [ExprStmt] ExprStmt +# 53| 0: [AssignExpr] ... = ... +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = prvalue +# 53| 0: [VariableAccess] cf3 +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = lvalue +# 53| 1: [RealImaginarySubExpr] ... - ... +# 53| Type = [ArithmeticType] _Complex float +# 53| ValueCategory = prvalue +# 53| 0: [VariableAccess] f1 +# 53| Type = [FloatType] float +# 53| ValueCategory = prvalue(load) +# 53| 1: [VariableAccess] jf2 +# 53| Type = [ArithmeticType] _Imaginary float +# 53| ValueCategory = prvalue(load) +# 54| 27: [ExprStmt] ExprStmt +# 54| 0: [AssignExpr] ... = ... +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue +# 54| 0: [VariableAccess] jf3 +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = lvalue +# 54| 1: [MulExpr] ... * ... +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue +# 54| 0: [VariableAccess] f1 +# 54| Type = [FloatType] float +# 54| ValueCategory = prvalue(load) +# 54| 1: [VariableAccess] jf2 +# 54| Type = [ArithmeticType] _Imaginary float +# 54| ValueCategory = prvalue(load) +# 55| 28: [ExprStmt] ExprStmt +# 55| 0: [AssignExpr] ... = ... +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue +# 55| 0: [VariableAccess] jf3 +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = lvalue +# 55| 1: [ImaginaryDivExpr] ... / ... +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue +# 55| 0: [VariableAccess] f1 +# 55| Type = [FloatType] float +# 55| ValueCategory = prvalue(load) +# 55| 1: [VariableAccess] jf2 +# 55| Type = [ArithmeticType] _Imaginary float +# 55| ValueCategory = prvalue(load) +# 56| 29: [ReturnStmt] return ... +# 58| [TopLevelFunction] void complex_conversions() +# 58| params: +# 58| body: [Block] { ... } +# 59| 0: [DeclStmt] declaration +# 59| 0: [VariableDeclarationEntry] definition of f +# 59| Type = [FloatType] float +# 59| init: [Initializer] initializer for f +# 59| expr: [CStyleCast] (float)... +# 59| Conversion = [FloatingPointConversion] floating point conversion +# 59| Type = [FloatType] float +# 59| Value = [CStyleCast] 2.0 +# 59| ValueCategory = prvalue +# 59| expr: [Literal] 2.0 +# 59| Type = [DoubleType] double +# 59| Value = [Literal] 2.0 +# 59| ValueCategory = prvalue +# 60| 1: [DeclStmt] declaration +# 60| 0: [VariableDeclarationEntry] definition of d +# 60| Type = [DoubleType] double +# 60| init: [Initializer] initializer for d +# 60| expr: [Literal] 3.0 +# 60| Type = [DoubleType] double +# 60| Value = [Literal] 3.0 +# 60| ValueCategory = prvalue +# 61| 2: [DeclStmt] declaration +# 61| 0: [VariableDeclarationEntry] definition of ld +# 61| Type = [LongDoubleType] long double +# 61| init: [Initializer] initializer for ld +# 61| expr: [CStyleCast] (long double)... +# 61| Conversion = [FloatingPointConversion] floating point conversion +# 61| Type = [LongDoubleType] long double +# 61| Value = [CStyleCast] 5.0 +# 61| ValueCategory = prvalue +# 61| expr: [Literal] 5.0 +# 61| Type = [DoubleType] double +# 61| Value = [Literal] 5.0 +# 61| ValueCategory = prvalue +# 62| 3: [DeclStmt] declaration +# 62| 0: [VariableDeclarationEntry] definition of cf +# 62| Type = [ArithmeticType] _Complex float +# 62| init: [Initializer] initializer for cf +# 62| expr: [CStyleCast] (_Complex float)... +# 62| Conversion = [FloatingPointConversion] floating point conversion +# 62| Type = [ArithmeticType] _Complex float +# 62| ValueCategory = prvalue +# 62| expr: [Literal] 7.0 +# 62| Type = [DoubleType] double +# 62| Value = [Literal] 7.0 +# 62| ValueCategory = prvalue +# 63| 4: [DeclStmt] declaration +# 63| 0: [VariableDeclarationEntry] definition of cd +# 63| Type = [ArithmeticType] _Complex double +# 63| init: [Initializer] initializer for cd +# 63| expr: [CStyleCast] (_Complex double)... +# 63| Conversion = [FloatingPointConversion] floating point conversion +# 63| Type = [ArithmeticType] _Complex double +# 63| ValueCategory = prvalue +# 63| expr: [Literal] 11.0 +# 63| Type = [DoubleType] double +# 63| Value = [Literal] 11.0 +# 63| ValueCategory = prvalue +# 64| 5: [DeclStmt] declaration +# 64| 0: [VariableDeclarationEntry] definition of cld +# 64| Type = [ArithmeticType] _Complex long double +# 64| init: [Initializer] initializer for cld +# 64| expr: [CStyleCast] (_Complex long double)... +# 64| Conversion = [FloatingPointConversion] floating point conversion +# 64| Type = [ArithmeticType] _Complex long double +# 64| ValueCategory = prvalue +# 64| expr: [Literal] 13.0 +# 64| Type = [DoubleType] double +# 64| Value = [Literal] 13.0 +# 64| ValueCategory = prvalue +# 65| 6: [DeclStmt] declaration +# 65| 0: [VariableDeclarationEntry] definition of jf +# 65| Type = [ArithmeticType] _Imaginary float +# 65| init: [Initializer] initializer for jf +# 65| expr: [Literal] 1.0i +# 65| Type = [ArithmeticType] _Imaginary float +# 65| Value = [Literal] 1.0i +# 65| ValueCategory = prvalue +# 66| 7: [DeclStmt] declaration +# 66| 0: [VariableDeclarationEntry] definition of jd +# 66| Type = [ArithmeticType] _Imaginary double +# 66| init: [Initializer] initializer for jd +# 66| expr: [CStyleCast] (_Imaginary double)... +# 66| Conversion = [FloatingPointConversion] floating point conversion +# 66| Type = [ArithmeticType] _Imaginary double +# 66| ValueCategory = prvalue +# 66| expr: [Literal] 1.0i +# 66| Type = [ArithmeticType] _Imaginary float +# 66| Value = [Literal] 1.0i +# 66| ValueCategory = prvalue +# 67| 8: [DeclStmt] declaration +# 67| 0: [VariableDeclarationEntry] definition of jld +# 67| Type = [ArithmeticType] _Imaginary long double +# 67| init: [Initializer] initializer for jld +# 67| expr: [CStyleCast] (_Imaginary long double)... +# 67| Conversion = [FloatingPointConversion] floating point conversion +# 67| Type = [ArithmeticType] _Imaginary long double +# 67| ValueCategory = prvalue +# 67| expr: [Literal] 1.0i +# 67| Type = [ArithmeticType] _Imaginary float +# 67| Value = [Literal] 1.0i +# 67| ValueCategory = prvalue +# 70| 9: [ExprStmt] ExprStmt +# 70| 0: [AssignExpr] ... = ... +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = prvalue +# 70| 0: [VariableAccess] cf +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = lvalue +# 70| 1: [VariableAccess] cf +# 70| Type = [ArithmeticType] _Complex float +# 70| ValueCategory = prvalue(load) +# 71| 10: [ExprStmt] ExprStmt +# 71| 0: [AssignExpr] ... = ... +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = prvalue +# 71| 0: [VariableAccess] cf +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = lvalue +# 71| 1: [CStyleCast] (_Complex float)... +# 71| Conversion = [FloatingPointConversion] floating point conversion +# 71| Type = [ArithmeticType] _Complex float +# 71| ValueCategory = prvalue +# 71| expr: [VariableAccess] cd +# 71| Type = [ArithmeticType] _Complex double +# 71| ValueCategory = prvalue(load) +# 72| 11: [ExprStmt] ExprStmt +# 72| 0: [AssignExpr] ... = ... +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = prvalue +# 72| 0: [VariableAccess] cf +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = lvalue +# 72| 1: [CStyleCast] (_Complex float)... +# 72| Conversion = [FloatingPointConversion] floating point conversion +# 72| Type = [ArithmeticType] _Complex float +# 72| ValueCategory = prvalue +# 72| expr: [VariableAccess] cld +# 72| Type = [ArithmeticType] _Complex long double +# 72| ValueCategory = prvalue(load) +# 73| 12: [ExprStmt] ExprStmt +# 73| 0: [AssignExpr] ... = ... +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = prvalue +# 73| 0: [VariableAccess] cd +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = lvalue +# 73| 1: [CStyleCast] (_Complex double)... +# 73| Conversion = [FloatingPointConversion] floating point conversion +# 73| Type = [ArithmeticType] _Complex double +# 73| ValueCategory = prvalue +# 73| expr: [VariableAccess] cf +# 73| Type = [ArithmeticType] _Complex float +# 73| ValueCategory = prvalue(load) +# 74| 13: [ExprStmt] ExprStmt +# 74| 0: [AssignExpr] ... = ... +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = prvalue +# 74| 0: [VariableAccess] cd +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = lvalue +# 74| 1: [VariableAccess] cd +# 74| Type = [ArithmeticType] _Complex double +# 74| ValueCategory = prvalue(load) +# 75| 14: [ExprStmt] ExprStmt +# 75| 0: [AssignExpr] ... = ... +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = prvalue +# 75| 0: [VariableAccess] cd +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = lvalue +# 75| 1: [CStyleCast] (_Complex double)... +# 75| Conversion = [FloatingPointConversion] floating point conversion +# 75| Type = [ArithmeticType] _Complex double +# 75| ValueCategory = prvalue +# 75| expr: [VariableAccess] cld +# 75| Type = [ArithmeticType] _Complex long double +# 75| ValueCategory = prvalue(load) +# 76| 15: [ExprStmt] ExprStmt +# 76| 0: [AssignExpr] ... = ... +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = prvalue +# 76| 0: [VariableAccess] cld +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = lvalue +# 76| 1: [CStyleCast] (_Complex long double)... +# 76| Conversion = [FloatingPointConversion] floating point conversion +# 76| Type = [ArithmeticType] _Complex long double +# 76| ValueCategory = prvalue +# 76| expr: [VariableAccess] cf +# 76| Type = [ArithmeticType] _Complex float +# 76| ValueCategory = prvalue(load) +# 77| 16: [ExprStmt] ExprStmt +# 77| 0: [AssignExpr] ... = ... +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = prvalue +# 77| 0: [VariableAccess] cld +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = lvalue +# 77| 1: [CStyleCast] (_Complex long double)... +# 77| Conversion = [FloatingPointConversion] floating point conversion +# 77| Type = [ArithmeticType] _Complex long double +# 77| ValueCategory = prvalue +# 77| expr: [VariableAccess] cd +# 77| Type = [ArithmeticType] _Complex double +# 77| ValueCategory = prvalue(load) +# 78| 17: [ExprStmt] ExprStmt +# 78| 0: [AssignExpr] ... = ... +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = prvalue +# 78| 0: [VariableAccess] cld +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = lvalue +# 78| 1: [VariableAccess] cld +# 78| Type = [ArithmeticType] _Complex long double +# 78| ValueCategory = prvalue(load) +# 81| 18: [ExprStmt] ExprStmt +# 81| 0: [AssignExpr] ... = ... +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = prvalue +# 81| 0: [VariableAccess] cf +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = lvalue +# 81| 1: [CStyleCast] (_Complex float)... +# 81| Conversion = [FloatingPointConversion] floating point conversion +# 81| Type = [ArithmeticType] _Complex float +# 81| ValueCategory = prvalue +# 81| expr: [VariableAccess] f +# 81| Type = [FloatType] float +# 81| ValueCategory = prvalue(load) +# 82| 19: [ExprStmt] ExprStmt +# 82| 0: [AssignExpr] ... = ... +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = prvalue +# 82| 0: [VariableAccess] cf +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = lvalue +# 82| 1: [CStyleCast] (_Complex float)... +# 82| Conversion = [FloatingPointConversion] floating point conversion +# 82| Type = [ArithmeticType] _Complex float +# 82| ValueCategory = prvalue +# 82| expr: [VariableAccess] d +# 82| Type = [DoubleType] double +# 82| ValueCategory = prvalue(load) +# 83| 20: [ExprStmt] ExprStmt +# 83| 0: [AssignExpr] ... = ... +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = prvalue +# 83| 0: [VariableAccess] cf +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = lvalue +# 83| 1: [CStyleCast] (_Complex float)... +# 83| Conversion = [FloatingPointConversion] floating point conversion +# 83| Type = [ArithmeticType] _Complex float +# 83| ValueCategory = prvalue +# 83| expr: [VariableAccess] ld +# 83| Type = [LongDoubleType] long double +# 83| ValueCategory = prvalue(load) +# 84| 21: [ExprStmt] ExprStmt +# 84| 0: [AssignExpr] ... = ... +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = prvalue +# 84| 0: [VariableAccess] cd +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = lvalue +# 84| 1: [CStyleCast] (_Complex double)... +# 84| Conversion = [FloatingPointConversion] floating point conversion +# 84| Type = [ArithmeticType] _Complex double +# 84| ValueCategory = prvalue +# 84| expr: [VariableAccess] f +# 84| Type = [FloatType] float +# 84| ValueCategory = prvalue(load) +# 85| 22: [ExprStmt] ExprStmt +# 85| 0: [AssignExpr] ... = ... +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = prvalue +# 85| 0: [VariableAccess] cd +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = lvalue +# 85| 1: [CStyleCast] (_Complex double)... +# 85| Conversion = [FloatingPointConversion] floating point conversion +# 85| Type = [ArithmeticType] _Complex double +# 85| ValueCategory = prvalue +# 85| expr: [VariableAccess] d +# 85| Type = [DoubleType] double +# 85| ValueCategory = prvalue(load) +# 86| 23: [ExprStmt] ExprStmt +# 86| 0: [AssignExpr] ... = ... +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = prvalue +# 86| 0: [VariableAccess] cd +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = lvalue +# 86| 1: [CStyleCast] (_Complex double)... +# 86| Conversion = [FloatingPointConversion] floating point conversion +# 86| Type = [ArithmeticType] _Complex double +# 86| ValueCategory = prvalue +# 86| expr: [VariableAccess] ld +# 86| Type = [LongDoubleType] long double +# 86| ValueCategory = prvalue(load) +# 87| 24: [ExprStmt] ExprStmt +# 87| 0: [AssignExpr] ... = ... +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = prvalue +# 87| 0: [VariableAccess] cld +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = lvalue +# 87| 1: [CStyleCast] (_Complex long double)... +# 87| Conversion = [FloatingPointConversion] floating point conversion +# 87| Type = [ArithmeticType] _Complex long double +# 87| ValueCategory = prvalue +# 87| expr: [VariableAccess] f +# 87| Type = [FloatType] float +# 87| ValueCategory = prvalue(load) +# 88| 25: [ExprStmt] ExprStmt +# 88| 0: [AssignExpr] ... = ... +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = prvalue +# 88| 0: [VariableAccess] cld +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = lvalue +# 88| 1: [CStyleCast] (_Complex long double)... +# 88| Conversion = [FloatingPointConversion] floating point conversion +# 88| Type = [ArithmeticType] _Complex long double +# 88| ValueCategory = prvalue +# 88| expr: [VariableAccess] d +# 88| Type = [DoubleType] double +# 88| ValueCategory = prvalue(load) +# 89| 26: [ExprStmt] ExprStmt +# 89| 0: [AssignExpr] ... = ... +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = prvalue +# 89| 0: [VariableAccess] cld +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = lvalue +# 89| 1: [CStyleCast] (_Complex long double)... +# 89| Conversion = [FloatingPointConversion] floating point conversion +# 89| Type = [ArithmeticType] _Complex long double +# 89| ValueCategory = prvalue +# 89| expr: [VariableAccess] ld +# 89| Type = [LongDoubleType] long double +# 89| ValueCategory = prvalue(load) +# 92| 27: [ExprStmt] ExprStmt +# 92| 0: [AssignExpr] ... = ... +# 92| Type = [FloatType] float +# 92| ValueCategory = prvalue +# 92| 0: [VariableAccess] f +# 92| Type = [FloatType] float +# 92| ValueCategory = lvalue +# 92| 1: [CStyleCast] (float)... +# 92| Conversion = [FloatingPointConversion] floating point conversion +# 92| Type = [FloatType] float +# 92| ValueCategory = prvalue +# 92| expr: [VariableAccess] cf +# 92| Type = [ArithmeticType] _Complex float +# 92| ValueCategory = prvalue(load) +# 93| 28: [ExprStmt] ExprStmt +# 93| 0: [AssignExpr] ... = ... +# 93| Type = [FloatType] float +# 93| ValueCategory = prvalue +# 93| 0: [VariableAccess] f +# 93| Type = [FloatType] float +# 93| ValueCategory = lvalue +# 93| 1: [CStyleCast] (float)... +# 93| Conversion = [FloatingPointConversion] floating point conversion +# 93| Type = [FloatType] float +# 93| ValueCategory = prvalue +# 93| expr: [VariableAccess] cd +# 93| Type = [ArithmeticType] _Complex double +# 93| ValueCategory = prvalue(load) +# 94| 29: [ExprStmt] ExprStmt +# 94| 0: [AssignExpr] ... = ... +# 94| Type = [FloatType] float +# 94| ValueCategory = prvalue +# 94| 0: [VariableAccess] f +# 94| Type = [FloatType] float +# 94| ValueCategory = lvalue +# 94| 1: [CStyleCast] (float)... +# 94| Conversion = [FloatingPointConversion] floating point conversion +# 94| Type = [FloatType] float +# 94| ValueCategory = prvalue +# 94| expr: [VariableAccess] cld +# 94| Type = [ArithmeticType] _Complex long double +# 94| ValueCategory = prvalue(load) +# 95| 30: [ExprStmt] ExprStmt +# 95| 0: [AssignExpr] ... = ... +# 95| Type = [DoubleType] double +# 95| ValueCategory = prvalue +# 95| 0: [VariableAccess] d +# 95| Type = [DoubleType] double +# 95| ValueCategory = lvalue +# 95| 1: [CStyleCast] (double)... +# 95| Conversion = [FloatingPointConversion] floating point conversion +# 95| Type = [DoubleType] double +# 95| ValueCategory = prvalue +# 95| expr: [VariableAccess] cf +# 95| Type = [ArithmeticType] _Complex float +# 95| ValueCategory = prvalue(load) +# 96| 31: [ExprStmt] ExprStmt +# 96| 0: [AssignExpr] ... = ... +# 96| Type = [DoubleType] double +# 96| ValueCategory = prvalue +# 96| 0: [VariableAccess] d +# 96| Type = [DoubleType] double +# 96| ValueCategory = lvalue +# 96| 1: [CStyleCast] (double)... +# 96| Conversion = [FloatingPointConversion] floating point conversion +# 96| Type = [DoubleType] double +# 96| ValueCategory = prvalue +# 96| expr: [VariableAccess] cd +# 96| Type = [ArithmeticType] _Complex double +# 96| ValueCategory = prvalue(load) +# 97| 32: [ExprStmt] ExprStmt +# 97| 0: [AssignExpr] ... = ... +# 97| Type = [DoubleType] double +# 97| ValueCategory = prvalue +# 97| 0: [VariableAccess] d +# 97| Type = [DoubleType] double +# 97| ValueCategory = lvalue +# 97| 1: [CStyleCast] (double)... +# 97| Conversion = [FloatingPointConversion] floating point conversion +# 97| Type = [DoubleType] double +# 97| ValueCategory = prvalue +# 97| expr: [VariableAccess] cld +# 97| Type = [ArithmeticType] _Complex long double +# 97| ValueCategory = prvalue(load) +# 98| 33: [ExprStmt] ExprStmt +# 98| 0: [AssignExpr] ... = ... +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = prvalue +# 98| 0: [VariableAccess] ld +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = lvalue +# 98| 1: [CStyleCast] (long double)... +# 98| Conversion = [FloatingPointConversion] floating point conversion +# 98| Type = [LongDoubleType] long double +# 98| ValueCategory = prvalue +# 98| expr: [VariableAccess] cf +# 98| Type = [ArithmeticType] _Complex float +# 98| ValueCategory = prvalue(load) +# 99| 34: [ExprStmt] ExprStmt +# 99| 0: [AssignExpr] ... = ... +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = prvalue +# 99| 0: [VariableAccess] ld +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = lvalue +# 99| 1: [CStyleCast] (long double)... +# 99| Conversion = [FloatingPointConversion] floating point conversion +# 99| Type = [LongDoubleType] long double +# 99| ValueCategory = prvalue +# 99| expr: [VariableAccess] cd +# 99| Type = [ArithmeticType] _Complex double +# 99| ValueCategory = prvalue(load) +# 100| 35: [ExprStmt] ExprStmt +# 100| 0: [AssignExpr] ... = ... +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = prvalue +# 100| 0: [VariableAccess] ld +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = lvalue +# 100| 1: [CStyleCast] (long double)... +# 100| Conversion = [FloatingPointConversion] floating point conversion +# 100| Type = [LongDoubleType] long double +# 100| ValueCategory = prvalue +# 100| expr: [VariableAccess] cld +# 100| Type = [ArithmeticType] _Complex long double +# 100| ValueCategory = prvalue(load) +# 103| 36: [ExprStmt] ExprStmt +# 103| 0: [AssignExpr] ... = ... +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = prvalue +# 103| 0: [VariableAccess] cf +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = lvalue +# 103| 1: [CStyleCast] (_Complex float)... +# 103| Conversion = [FloatingPointConversion] floating point conversion +# 103| Type = [ArithmeticType] _Complex float +# 103| ValueCategory = prvalue +# 103| expr: [VariableAccess] jf +# 103| Type = [ArithmeticType] _Imaginary float +# 103| ValueCategory = prvalue(load) +# 104| 37: [ExprStmt] ExprStmt +# 104| 0: [AssignExpr] ... = ... +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = prvalue +# 104| 0: [VariableAccess] cf +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = lvalue +# 104| 1: [CStyleCast] (_Complex float)... +# 104| Conversion = [FloatingPointConversion] floating point conversion +# 104| Type = [ArithmeticType] _Complex float +# 104| ValueCategory = prvalue +# 104| expr: [VariableAccess] jd +# 104| Type = [ArithmeticType] _Imaginary double +# 104| ValueCategory = prvalue(load) +# 105| 38: [ExprStmt] ExprStmt +# 105| 0: [AssignExpr] ... = ... +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = prvalue +# 105| 0: [VariableAccess] cf +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = lvalue +# 105| 1: [CStyleCast] (_Complex float)... +# 105| Conversion = [FloatingPointConversion] floating point conversion +# 105| Type = [ArithmeticType] _Complex float +# 105| ValueCategory = prvalue +# 105| expr: [VariableAccess] jld +# 105| Type = [ArithmeticType] _Imaginary long double +# 105| ValueCategory = prvalue(load) +# 106| 39: [ExprStmt] ExprStmt +# 106| 0: [AssignExpr] ... = ... +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = prvalue +# 106| 0: [VariableAccess] cd +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = lvalue +# 106| 1: [CStyleCast] (_Complex double)... +# 106| Conversion = [FloatingPointConversion] floating point conversion +# 106| Type = [ArithmeticType] _Complex double +# 106| ValueCategory = prvalue +# 106| expr: [VariableAccess] jf +# 106| Type = [ArithmeticType] _Imaginary float +# 106| ValueCategory = prvalue(load) +# 107| 40: [ExprStmt] ExprStmt +# 107| 0: [AssignExpr] ... = ... +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = prvalue +# 107| 0: [VariableAccess] cd +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = lvalue +# 107| 1: [CStyleCast] (_Complex double)... +# 107| Conversion = [FloatingPointConversion] floating point conversion +# 107| Type = [ArithmeticType] _Complex double +# 107| ValueCategory = prvalue +# 107| expr: [VariableAccess] jd +# 107| Type = [ArithmeticType] _Imaginary double +# 107| ValueCategory = prvalue(load) +# 108| 41: [ExprStmt] ExprStmt +# 108| 0: [AssignExpr] ... = ... +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = prvalue +# 108| 0: [VariableAccess] cd +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = lvalue +# 108| 1: [CStyleCast] (_Complex double)... +# 108| Conversion = [FloatingPointConversion] floating point conversion +# 108| Type = [ArithmeticType] _Complex double +# 108| ValueCategory = prvalue +# 108| expr: [VariableAccess] jld +# 108| Type = [ArithmeticType] _Imaginary long double +# 108| ValueCategory = prvalue(load) +# 109| 42: [ExprStmt] ExprStmt +# 109| 0: [AssignExpr] ... = ... +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = prvalue +# 109| 0: [VariableAccess] cld +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = lvalue +# 109| 1: [CStyleCast] (_Complex long double)... +# 109| Conversion = [FloatingPointConversion] floating point conversion +# 109| Type = [ArithmeticType] _Complex long double +# 109| ValueCategory = prvalue +# 109| expr: [VariableAccess] jf +# 109| Type = [ArithmeticType] _Imaginary float +# 109| ValueCategory = prvalue(load) +# 110| 43: [ExprStmt] ExprStmt +# 110| 0: [AssignExpr] ... = ... +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = prvalue +# 110| 0: [VariableAccess] cld +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = lvalue +# 110| 1: [CStyleCast] (_Complex long double)... +# 110| Conversion = [FloatingPointConversion] floating point conversion +# 110| Type = [ArithmeticType] _Complex long double +# 110| ValueCategory = prvalue +# 110| expr: [VariableAccess] jd +# 110| Type = [ArithmeticType] _Imaginary double +# 110| ValueCategory = prvalue(load) +# 111| 44: [ExprStmt] ExprStmt +# 111| 0: [AssignExpr] ... = ... +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = prvalue +# 111| 0: [VariableAccess] cld +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = lvalue +# 111| 1: [CStyleCast] (_Complex long double)... +# 111| Conversion = [FloatingPointConversion] floating point conversion +# 111| Type = [ArithmeticType] _Complex long double +# 111| ValueCategory = prvalue +# 111| expr: [VariableAccess] jld +# 111| Type = [ArithmeticType] _Imaginary long double +# 111| ValueCategory = prvalue(load) +# 114| 45: [ExprStmt] ExprStmt +# 114| 0: [AssignExpr] ... = ... +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = prvalue +# 114| 0: [VariableAccess] jf +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = lvalue +# 114| 1: [CStyleCast] (_Imaginary float)... +# 114| Conversion = [FloatingPointConversion] floating point conversion +# 114| Type = [ArithmeticType] _Imaginary float +# 114| ValueCategory = prvalue +# 114| expr: [VariableAccess] cf +# 114| Type = [ArithmeticType] _Complex float +# 114| ValueCategory = prvalue(load) +# 115| 46: [ExprStmt] ExprStmt +# 115| 0: [AssignExpr] ... = ... +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = prvalue +# 115| 0: [VariableAccess] jf +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = lvalue +# 115| 1: [CStyleCast] (_Imaginary float)... +# 115| Conversion = [FloatingPointConversion] floating point conversion +# 115| Type = [ArithmeticType] _Imaginary float +# 115| ValueCategory = prvalue +# 115| expr: [VariableAccess] cd +# 115| Type = [ArithmeticType] _Complex double +# 115| ValueCategory = prvalue(load) +# 116| 47: [ExprStmt] ExprStmt +# 116| 0: [AssignExpr] ... = ... +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = prvalue +# 116| 0: [VariableAccess] jf +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = lvalue +# 116| 1: [CStyleCast] (_Imaginary float)... +# 116| Conversion = [FloatingPointConversion] floating point conversion +# 116| Type = [ArithmeticType] _Imaginary float +# 116| ValueCategory = prvalue +# 116| expr: [VariableAccess] cld +# 116| Type = [ArithmeticType] _Complex long double +# 116| ValueCategory = prvalue(load) +# 117| 48: [ExprStmt] ExprStmt +# 117| 0: [AssignExpr] ... = ... +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = prvalue +# 117| 0: [VariableAccess] jd +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = lvalue +# 117| 1: [CStyleCast] (_Imaginary double)... +# 117| Conversion = [FloatingPointConversion] floating point conversion +# 117| Type = [ArithmeticType] _Imaginary double +# 117| ValueCategory = prvalue +# 117| expr: [VariableAccess] cf +# 117| Type = [ArithmeticType] _Complex float +# 117| ValueCategory = prvalue(load) +# 118| 49: [ExprStmt] ExprStmt +# 118| 0: [AssignExpr] ... = ... +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = prvalue +# 118| 0: [VariableAccess] jd +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = lvalue +# 118| 1: [CStyleCast] (_Imaginary double)... +# 118| Conversion = [FloatingPointConversion] floating point conversion +# 118| Type = [ArithmeticType] _Imaginary double +# 118| ValueCategory = prvalue +# 118| expr: [VariableAccess] cd +# 118| Type = [ArithmeticType] _Complex double +# 118| ValueCategory = prvalue(load) +# 119| 50: [ExprStmt] ExprStmt +# 119| 0: [AssignExpr] ... = ... +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = prvalue +# 119| 0: [VariableAccess] jd +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = lvalue +# 119| 1: [CStyleCast] (_Imaginary double)... +# 119| Conversion = [FloatingPointConversion] floating point conversion +# 119| Type = [ArithmeticType] _Imaginary double +# 119| ValueCategory = prvalue +# 119| expr: [VariableAccess] cld +# 119| Type = [ArithmeticType] _Complex long double +# 119| ValueCategory = prvalue(load) +# 120| 51: [ExprStmt] ExprStmt +# 120| 0: [AssignExpr] ... = ... +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = prvalue +# 120| 0: [VariableAccess] jld +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = lvalue +# 120| 1: [CStyleCast] (_Imaginary long double)... +# 120| Conversion = [FloatingPointConversion] floating point conversion +# 120| Type = [ArithmeticType] _Imaginary long double +# 120| ValueCategory = prvalue +# 120| expr: [VariableAccess] cf +# 120| Type = [ArithmeticType] _Complex float +# 120| ValueCategory = prvalue(load) +# 121| 52: [ExprStmt] ExprStmt +# 121| 0: [AssignExpr] ... = ... +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = prvalue +# 121| 0: [VariableAccess] jld +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = lvalue +# 121| 1: [CStyleCast] (_Imaginary long double)... +# 121| Conversion = [FloatingPointConversion] floating point conversion +# 121| Type = [ArithmeticType] _Imaginary long double +# 121| ValueCategory = prvalue +# 121| expr: [VariableAccess] cd +# 121| Type = [ArithmeticType] _Complex double +# 121| ValueCategory = prvalue(load) +# 122| 53: [ExprStmt] ExprStmt +# 122| 0: [AssignExpr] ... = ... +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = prvalue +# 122| 0: [VariableAccess] jld +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = lvalue +# 122| 1: [CStyleCast] (_Imaginary long double)... +# 122| Conversion = [FloatingPointConversion] floating point conversion +# 122| Type = [ArithmeticType] _Imaginary long double +# 122| ValueCategory = prvalue +# 122| expr: [VariableAccess] cld +# 122| Type = [ArithmeticType] _Complex long double +# 122| ValueCategory = prvalue(load) +# 125| 54: [ExprStmt] ExprStmt +# 125| 0: [AssignExpr] ... = ... +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = prvalue +# 125| 0: [VariableAccess] jf +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = lvalue +# 125| 1: [CStyleCast] (_Imaginary float)... +# 125| Conversion = [FloatingPointConversion] floating point conversion +# 125| Type = [ArithmeticType] _Imaginary float +# 125| ValueCategory = prvalue +# 125| expr: [VariableAccess] f +# 125| Type = [FloatType] float +# 125| ValueCategory = prvalue(load) +# 126| 55: [ExprStmt] ExprStmt +# 126| 0: [AssignExpr] ... = ... +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = prvalue +# 126| 0: [VariableAccess] jf +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = lvalue +# 126| 1: [CStyleCast] (_Imaginary float)... +# 126| Conversion = [FloatingPointConversion] floating point conversion +# 126| Type = [ArithmeticType] _Imaginary float +# 126| ValueCategory = prvalue +# 126| expr: [VariableAccess] d +# 126| Type = [DoubleType] double +# 126| ValueCategory = prvalue(load) +# 127| 56: [ExprStmt] ExprStmt +# 127| 0: [AssignExpr] ... = ... +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = prvalue +# 127| 0: [VariableAccess] jf +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = lvalue +# 127| 1: [CStyleCast] (_Imaginary float)... +# 127| Conversion = [FloatingPointConversion] floating point conversion +# 127| Type = [ArithmeticType] _Imaginary float +# 127| ValueCategory = prvalue +# 127| expr: [VariableAccess] ld +# 127| Type = [LongDoubleType] long double +# 127| ValueCategory = prvalue(load) +# 128| 57: [ExprStmt] ExprStmt +# 128| 0: [AssignExpr] ... = ... +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = prvalue +# 128| 0: [VariableAccess] jd +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = lvalue +# 128| 1: [CStyleCast] (_Imaginary double)... +# 128| Conversion = [FloatingPointConversion] floating point conversion +# 128| Type = [ArithmeticType] _Imaginary double +# 128| ValueCategory = prvalue +# 128| expr: [VariableAccess] f +# 128| Type = [FloatType] float +# 128| ValueCategory = prvalue(load) +# 129| 58: [ExprStmt] ExprStmt +# 129| 0: [AssignExpr] ... = ... +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = prvalue +# 129| 0: [VariableAccess] jd +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = lvalue +# 129| 1: [CStyleCast] (_Imaginary double)... +# 129| Conversion = [FloatingPointConversion] floating point conversion +# 129| Type = [ArithmeticType] _Imaginary double +# 129| ValueCategory = prvalue +# 129| expr: [VariableAccess] d +# 129| Type = [DoubleType] double +# 129| ValueCategory = prvalue(load) +# 130| 59: [ExprStmt] ExprStmt +# 130| 0: [AssignExpr] ... = ... +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = prvalue +# 130| 0: [VariableAccess] jd +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = lvalue +# 130| 1: [CStyleCast] (_Imaginary double)... +# 130| Conversion = [FloatingPointConversion] floating point conversion +# 130| Type = [ArithmeticType] _Imaginary double +# 130| ValueCategory = prvalue +# 130| expr: [VariableAccess] ld +# 130| Type = [LongDoubleType] long double +# 130| ValueCategory = prvalue(load) +# 131| 60: [ExprStmt] ExprStmt +# 131| 0: [AssignExpr] ... = ... +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = prvalue +# 131| 0: [VariableAccess] jld +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = lvalue +# 131| 1: [CStyleCast] (_Imaginary long double)... +# 131| Conversion = [FloatingPointConversion] floating point conversion +# 131| Type = [ArithmeticType] _Imaginary long double +# 131| ValueCategory = prvalue +# 131| expr: [VariableAccess] f +# 131| Type = [FloatType] float +# 131| ValueCategory = prvalue(load) +# 132| 61: [ExprStmt] ExprStmt +# 132| 0: [AssignExpr] ... = ... +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = prvalue +# 132| 0: [VariableAccess] jld +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = lvalue +# 132| 1: [CStyleCast] (_Imaginary long double)... +# 132| Conversion = [FloatingPointConversion] floating point conversion +# 132| Type = [ArithmeticType] _Imaginary long double +# 132| ValueCategory = prvalue +# 132| expr: [VariableAccess] d +# 132| Type = [DoubleType] double +# 132| ValueCategory = prvalue(load) +# 133| 62: [ExprStmt] ExprStmt +# 133| 0: [AssignExpr] ... = ... +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = prvalue +# 133| 0: [VariableAccess] jld +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = lvalue +# 133| 1: [CStyleCast] (_Imaginary long double)... +# 133| Conversion = [FloatingPointConversion] floating point conversion +# 133| Type = [ArithmeticType] _Imaginary long double +# 133| ValueCategory = prvalue +# 133| expr: [VariableAccess] ld +# 133| Type = [LongDoubleType] long double +# 133| ValueCategory = prvalue(load) +# 136| 63: [ExprStmt] ExprStmt +# 136| 0: [AssignExpr] ... = ... +# 136| Type = [FloatType] float +# 136| ValueCategory = prvalue +# 136| 0: [VariableAccess] f +# 136| Type = [FloatType] float +# 136| ValueCategory = lvalue +# 136| 1: [CStyleCast] (float)... +# 136| Conversion = [FloatingPointConversion] floating point conversion +# 136| Type = [FloatType] float +# 136| ValueCategory = prvalue +# 136| expr: [VariableAccess] jf +# 136| Type = [ArithmeticType] _Imaginary float +# 136| ValueCategory = prvalue(load) +# 137| 64: [ExprStmt] ExprStmt +# 137| 0: [AssignExpr] ... = ... +# 137| Type = [FloatType] float +# 137| ValueCategory = prvalue +# 137| 0: [VariableAccess] f +# 137| Type = [FloatType] float +# 137| ValueCategory = lvalue +# 137| 1: [CStyleCast] (float)... +# 137| Conversion = [FloatingPointConversion] floating point conversion +# 137| Type = [FloatType] float +# 137| ValueCategory = prvalue +# 137| expr: [VariableAccess] jd +# 137| Type = [ArithmeticType] _Imaginary double +# 137| ValueCategory = prvalue(load) +# 138| 65: [ExprStmt] ExprStmt +# 138| 0: [AssignExpr] ... = ... +# 138| Type = [FloatType] float +# 138| ValueCategory = prvalue +# 138| 0: [VariableAccess] f +# 138| Type = [FloatType] float +# 138| ValueCategory = lvalue +# 138| 1: [CStyleCast] (float)... +# 138| Conversion = [FloatingPointConversion] floating point conversion +# 138| Type = [FloatType] float +# 138| ValueCategory = prvalue +# 138| expr: [VariableAccess] jld +# 138| Type = [ArithmeticType] _Imaginary long double +# 138| ValueCategory = prvalue(load) +# 139| 66: [ExprStmt] ExprStmt +# 139| 0: [AssignExpr] ... = ... +# 139| Type = [DoubleType] double +# 139| ValueCategory = prvalue +# 139| 0: [VariableAccess] d +# 139| Type = [DoubleType] double +# 139| ValueCategory = lvalue +# 139| 1: [CStyleCast] (double)... +# 139| Conversion = [FloatingPointConversion] floating point conversion +# 139| Type = [DoubleType] double +# 139| ValueCategory = prvalue +# 139| expr: [VariableAccess] jf +# 139| Type = [ArithmeticType] _Imaginary float +# 139| ValueCategory = prvalue(load) +# 140| 67: [ExprStmt] ExprStmt +# 140| 0: [AssignExpr] ... = ... +# 140| Type = [DoubleType] double +# 140| ValueCategory = prvalue +# 140| 0: [VariableAccess] d +# 140| Type = [DoubleType] double +# 140| ValueCategory = lvalue +# 140| 1: [CStyleCast] (double)... +# 140| Conversion = [FloatingPointConversion] floating point conversion +# 140| Type = [DoubleType] double +# 140| ValueCategory = prvalue +# 140| expr: [VariableAccess] jd +# 140| Type = [ArithmeticType] _Imaginary double +# 140| ValueCategory = prvalue(load) +# 141| 68: [ExprStmt] ExprStmt +# 141| 0: [AssignExpr] ... = ... +# 141| Type = [DoubleType] double +# 141| ValueCategory = prvalue +# 141| 0: [VariableAccess] d +# 141| Type = [DoubleType] double +# 141| ValueCategory = lvalue +# 141| 1: [CStyleCast] (double)... +# 141| Conversion = [FloatingPointConversion] floating point conversion +# 141| Type = [DoubleType] double +# 141| ValueCategory = prvalue +# 141| expr: [VariableAccess] jld +# 141| Type = [ArithmeticType] _Imaginary long double +# 141| ValueCategory = prvalue(load) +# 142| 69: [ExprStmt] ExprStmt +# 142| 0: [AssignExpr] ... = ... +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = prvalue +# 142| 0: [VariableAccess] ld +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = lvalue +# 142| 1: [CStyleCast] (long double)... +# 142| Conversion = [FloatingPointConversion] floating point conversion +# 142| Type = [LongDoubleType] long double +# 142| ValueCategory = prvalue +# 142| expr: [VariableAccess] jf +# 142| Type = [ArithmeticType] _Imaginary float +# 142| ValueCategory = prvalue(load) +# 143| 70: [ExprStmt] ExprStmt +# 143| 0: [AssignExpr] ... = ... +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = prvalue +# 143| 0: [VariableAccess] ld +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = lvalue +# 143| 1: [CStyleCast] (long double)... +# 143| Conversion = [FloatingPointConversion] floating point conversion +# 143| Type = [LongDoubleType] long double +# 143| ValueCategory = prvalue +# 143| expr: [VariableAccess] jd +# 143| Type = [ArithmeticType] _Imaginary double +# 143| ValueCategory = prvalue(load) +# 144| 71: [ExprStmt] ExprStmt +# 144| 0: [AssignExpr] ... = ... +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = prvalue +# 144| 0: [VariableAccess] ld +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = lvalue +# 144| 1: [CStyleCast] (long double)... +# 144| Conversion = [FloatingPointConversion] floating point conversion +# 144| Type = [LongDoubleType] long double +# 144| ValueCategory = prvalue +# 144| expr: [VariableAccess] jld +# 144| Type = [ArithmeticType] _Imaginary long double +# 144| ValueCategory = prvalue(load) +# 145| 72: [ReturnStmt] return ... ir.cpp: # 1| [TopLevelFunction] void Constants() # 1| params: @@ -4048,6 +5529,27 @@ ir.cpp: #-----| Type = [RValueReferenceType] C && # 628| [Destructor] void C::~C() # 628| params: +#-----| body: [Block] { ... } +#-----| 0: [ReturnStmt] return ... +# 628| destructions: +# 628| 0: [DestructorFieldDestruction] destructor field destruction of m_f +# 628| Type = [Struct] String +# 628| ValueCategory = prvalue +# 628| 0: [DestructorCall] call to ~String +# 628| Type = [VoidType] void +# 628| ValueCategory = prvalue +# 628| -1: [ImplicitThisFieldAccess] m_f +# 628| Type = [Struct] String +# 628| ValueCategory = lvalue +# 628| 1: [DestructorFieldDestruction] destructor field destruction of m_b +# 628| Type = [Struct] String +# 628| ValueCategory = prvalue +# 628| 0: [DestructorCall] call to ~String +# 628| Type = [VoidType] void +# 628| ValueCategory = prvalue +# 628| -1: [ImplicitThisFieldAccess] m_b +# 628| Type = [Struct] String +# 628| ValueCategory = lvalue # 630| [MemberFunction] int C::StaticMemberFunction(int) # 630| params: # 630| 0: [Parameter] x @@ -8475,6 +9977,294 @@ ir.cpp: # 1243| Type = [PointerType] const char * # 1243| ValueCategory = prvalue(load) # 1244| 3: [ReturnStmt] return ... +# 1248| [TopLevelFunction] char* strcpy(char*, char const*) +# 1248| params: +# 1248| 0: [Parameter] destination +# 1248| Type = [CharPointerType] char * +# 1248| 1: [Parameter] source +# 1248| Type = [PointerType] const char * +# 1249| [TopLevelFunction] char* strcat(char*, char const*) +# 1249| params: +# 1249| 0: [Parameter] destination +# 1249| Type = [CharPointerType] char * +# 1249| 1: [Parameter] source +# 1249| Type = [PointerType] const char * +# 1251| [TopLevelFunction] void test_strings(char*, char*) +# 1251| params: +# 1251| 0: [Parameter] s1 +# 1251| Type = [CharPointerType] char * +# 1251| 1: [Parameter] s2 +# 1251| Type = [CharPointerType] char * +# 1251| body: [Block] { ... } +# 1252| 0: [DeclStmt] declaration +# 1252| 0: [VariableDeclarationEntry] definition of buffer +# 1252| Type = [ArrayType] char[1024] +# 1252| init: [Initializer] initializer for buffer +# 1252| expr: [ArrayAggregateLiteral] {...} +# 1252| Type = [ArrayType] char[1024] +# 1252| ValueCategory = prvalue +# 1252| [0]: [CStyleCast] (char)... +# 1252| Conversion = [IntegralConversion] integral conversion +# 1252| Type = [PlainCharType] char +# 1252| Value = [CStyleCast] 0 +# 1252| ValueCategory = prvalue +# 1252| expr: [Literal] 0 +# 1252| Type = [IntType] int +# 1252| Value = [Literal] 0 +# 1252| ValueCategory = prvalue +# 1254| 1: [ExprStmt] ExprStmt +# 1254| 0: [FunctionCall] call to strcpy +# 1254| Type = [CharPointerType] char * +# 1254| ValueCategory = prvalue +# 1254| 0: [ArrayToPointerConversion] array to pointer conversion +# 1254| Type = [CharPointerType] char * +# 1254| ValueCategory = prvalue +# 1254| expr: [VariableAccess] buffer +# 1254| Type = [ArrayType] char[1024] +# 1254| ValueCategory = lvalue +# 1254| 1: [CStyleCast] (const char *)... +# 1254| Conversion = [PointerConversion] pointer conversion +# 1254| Type = [PointerType] const char * +# 1254| ValueCategory = prvalue +# 1254| expr: [VariableAccess] s1 +# 1254| Type = [CharPointerType] char * +# 1254| ValueCategory = prvalue(load) +# 1255| 2: [ExprStmt] ExprStmt +# 1255| 0: [FunctionCall] call to strcat +# 1255| Type = [CharPointerType] char * +# 1255| ValueCategory = prvalue +# 1255| 0: [ArrayToPointerConversion] array to pointer conversion +# 1255| Type = [CharPointerType] char * +# 1255| ValueCategory = prvalue +# 1255| expr: [VariableAccess] buffer +# 1255| Type = [ArrayType] char[1024] +# 1255| ValueCategory = lvalue +# 1255| 1: [CStyleCast] (const char *)... +# 1255| Conversion = [PointerConversion] pointer conversion +# 1255| Type = [PointerType] const char * +# 1255| ValueCategory = prvalue +# 1255| expr: [VariableAccess] s2 +# 1255| Type = [CharPointerType] char * +# 1255| ValueCategory = prvalue(load) +# 1256| 3: [ReturnStmt] return ... +# 1258| [CopyAssignmentOperator] A& A::operator=(A const&) +# 1258| params: +#-----| 0: [Parameter] p#0 +#-----| Type = [LValueReferenceType] const A & +# 1258| [MoveAssignmentOperator] A& A::operator=(A&&) +# 1258| params: +#-----| 0: [Parameter] p#0 +#-----| Type = [RValueReferenceType] A && +# 1261| [MemberFunction] void A::static_member(A*, int) +# 1261| params: +# 1261| 0: [Parameter] a +# 1261| Type = [PointerType] A * +# 1261| 1: [Parameter] x +# 1261| Type = [IntType] int +# 1261| body: [Block] { ... } +# 1262| 0: [ExprStmt] ExprStmt +# 1262| 0: [AssignExpr] ... = ... +# 1262| Type = [IntType] int +# 1262| ValueCategory = lvalue +# 1262| 0: [PointerFieldAccess] member +# 1262| Type = [IntType] int +# 1262| ValueCategory = lvalue +# 1262| -1: [VariableAccess] a +# 1262| Type = [PointerType] A * +# 1262| ValueCategory = prvalue(load) +# 1262| 1: [VariableAccess] x +# 1262| Type = [IntType] int +# 1262| ValueCategory = prvalue(load) +# 1263| 1: [ReturnStmt] return ... +# 1265| [MemberFunction] void A::static_member_without_def() +# 1265| params: +# 1268| [TopLevelFunction] A* getAnInstanceOfA() +# 1268| params: +# 1270| [TopLevelFunction] void test_static_member_functions(int, A*) +# 1270| params: +# 1270| 0: [Parameter] int_arg +# 1270| Type = [IntType] int +# 1270| 1: [Parameter] a_arg +# 1270| Type = [PointerType] A * +# 1270| body: [Block] { ... } +# 1271| 0: [DeclStmt] declaration +# 1271| 0: [VariableDeclarationEntry] definition of c +# 1271| Type = [Class] C +# 1271| init: [Initializer] initializer for c +# 1271| expr: [ConstructorCall] call to C +# 1271| Type = [VoidType] void +# 1271| ValueCategory = prvalue +# 1272| 1: [ExprStmt] ExprStmt +# 1272| 0: [FunctionCall] call to StaticMemberFunction +# 1272| Type = [IntType] int +# 1272| ValueCategory = prvalue +# 1272| -1: [VariableAccess] c +# 1272| Type = [Class] C +# 1272| ValueCategory = lvalue +# 1272| 0: [Literal] 10 +# 1272| Type = [IntType] int +# 1272| Value = [Literal] 10 +# 1272| ValueCategory = prvalue +# 1273| 2: [ExprStmt] ExprStmt +# 1273| 0: [FunctionCall] call to StaticMemberFunction +# 1273| Type = [IntType] int +# 1273| ValueCategory = prvalue +# 1273| 0: [Literal] 10 +# 1273| Type = [IntType] int +# 1273| Value = [Literal] 10 +# 1273| ValueCategory = prvalue +# 1275| 3: [DeclStmt] declaration +# 1275| 0: [VariableDeclarationEntry] definition of a +# 1275| Type = [Struct] A +# 1276| 4: [ExprStmt] ExprStmt +# 1276| 0: [FunctionCall] call to static_member +# 1276| Type = [VoidType] void +# 1276| ValueCategory = prvalue +# 1276| -1: [VariableAccess] a +# 1276| Type = [Struct] A +# 1276| ValueCategory = lvalue +# 1276| 0: [AddressOfExpr] & ... +# 1276| Type = [PointerType] A * +# 1276| ValueCategory = prvalue +# 1276| 0: [VariableAccess] a +# 1276| Type = [Struct] A +# 1276| ValueCategory = lvalue +# 1276| 1: [VariableAccess] int_arg +# 1276| Type = [IntType] int +# 1276| ValueCategory = prvalue(load) +# 1277| 5: [ExprStmt] ExprStmt +# 1277| 0: [FunctionCall] call to static_member +# 1277| Type = [VoidType] void +# 1277| ValueCategory = prvalue +# 1277| 0: [AddressOfExpr] & ... +# 1277| Type = [PointerType] A * +# 1277| ValueCategory = prvalue +# 1277| 0: [VariableAccess] a +# 1277| Type = [Struct] A +# 1277| ValueCategory = lvalue +# 1277| 1: [VariableAccess] int_arg +# 1277| Type = [IntType] int +# 1277| ValueCategory = prvalue(load) +# 1279| 6: [ExprStmt] ExprStmt +# 1279| 0: [FunctionCall] call to static_member +# 1279| Type = [VoidType] void +# 1279| ValueCategory = prvalue +# 1279| -1: [ParenthesisExpr] (...) +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue +# 1279| expr: [AddressOfExpr] & ... +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue +# 1279| 0: [VariableAccess] a +# 1279| Type = [Struct] A +# 1279| ValueCategory = lvalue +# 1279| 0: [VariableAccess] a_arg +# 1279| Type = [PointerType] A * +# 1279| ValueCategory = prvalue(load) +# 1279| 1: [AddExpr] ... + ... +# 1279| Type = [IntType] int +# 1279| ValueCategory = prvalue +# 1279| 0: [VariableAccess] int_arg +# 1279| Type = [IntType] int +# 1279| ValueCategory = prvalue(load) +# 1279| 1: [Literal] 2 +# 1279| Type = [IntType] int +# 1279| Value = [Literal] 2 +# 1279| ValueCategory = prvalue +# 1280| 7: [ExprStmt] ExprStmt +# 1280| 0: [FunctionCall] call to static_member +# 1280| Type = [VoidType] void +# 1280| ValueCategory = prvalue +# 1280| -1: [ParenthesisExpr] (...) +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| expr: [PointerDereferenceExpr] * ... +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| 0: [VariableAccess] a_arg +# 1280| Type = [PointerType] A * +# 1280| ValueCategory = prvalue(load) +# 1280| 0: [AddressOfExpr] & ... +# 1280| Type = [PointerType] A * +# 1280| ValueCategory = prvalue +# 1280| 0: [VariableAccess] a +# 1280| Type = [Struct] A +# 1280| ValueCategory = lvalue +# 1280| 1: [Literal] 99 +# 1280| Type = [IntType] int +# 1280| Value = [Literal] 99 +# 1280| ValueCategory = prvalue +# 1281| 8: [ExprStmt] ExprStmt +# 1281| 0: [FunctionCall] call to static_member +# 1281| Type = [VoidType] void +# 1281| ValueCategory = prvalue +# 1281| -1: [VariableAccess] a_arg +# 1281| Type = [PointerType] A * +# 1281| ValueCategory = prvalue(load) +# 1281| 0: [VariableAccess] a_arg +# 1281| Type = [PointerType] A * +# 1281| ValueCategory = prvalue(load) +# 1281| 1: [UnaryMinusExpr] - ... +# 1281| Type = [IntType] int +# 1281| Value = [UnaryMinusExpr] -1 +# 1281| ValueCategory = prvalue +# 1281| 0: [Literal] 1 +# 1281| Type = [IntType] int +# 1281| Value = [Literal] 1 +# 1281| ValueCategory = prvalue +# 1283| 9: [ExprStmt] ExprStmt +# 1283| 0: [FunctionCall] call to static_member_without_def +# 1283| Type = [VoidType] void +# 1283| ValueCategory = prvalue +# 1283| -1: [VariableAccess] a +# 1283| Type = [Struct] A +# 1283| ValueCategory = lvalue +# 1284| 10: [ExprStmt] ExprStmt +# 1284| 0: [FunctionCall] call to static_member_without_def +# 1284| Type = [VoidType] void +# 1284| ValueCategory = prvalue +# 1286| 11: [ExprStmt] ExprStmt +# 1286| 0: [FunctionCall] call to static_member_without_def +# 1286| Type = [VoidType] void +# 1286| ValueCategory = prvalue +# 1286| -1: [FunctionCall] call to getAnInstanceOfA +# 1286| Type = [PointerType] A * +# 1286| ValueCategory = prvalue +# 1287| 12: [ReturnStmt] return ... +# 1289| [TopLevelFunction] int missingReturnValue(bool, int) +# 1289| params: +# 1289| 0: [Parameter] b +# 1289| Type = [BoolType] bool +# 1289| 1: [Parameter] x +# 1289| Type = [IntType] int +# 1289| body: [Block] { ... } +# 1290| 0: [IfStmt] if (...) ... +# 1290| 0: [VariableAccess] b +# 1290| Type = [BoolType] bool +# 1290| ValueCategory = prvalue(load) +# 1290| 1: [Block] { ... } +# 1291| 0: [ReturnStmt] return ... +# 1291| 0: [VariableAccess] x +# 1291| Type = [IntType] int +# 1291| ValueCategory = prvalue(load) +# 1293| 1: [ReturnStmt] return ... +# 1295| [TopLevelFunction] void returnVoid(int, int) +# 1295| params: +# 1295| 0: [Parameter] x +# 1295| Type = [IntType] int +# 1295| 1: [Parameter] y +# 1295| Type = [IntType] int +# 1295| body: [Block] { ... } +# 1296| 0: [ReturnStmt] return ... +# 1296| 0: [FunctionCall] call to IntegerOps +# 1296| Type = [VoidType] void +# 1296| ValueCategory = prvalue +# 1296| 0: [VariableAccess] x +# 1296| Type = [IntType] int +# 1296| ValueCategory = prvalue(load) +# 1296| 1: [VariableAccess] y +# 1296| Type = [IntType] int +# 1296| ValueCategory = prvalue(load) perf-regression.cpp: # 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&) # 4| params: diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity_unsound.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/complex.c b/cpp/ql/test/library-tests/ir/ir/complex.c new file mode 100644 index 00000000000..d2009778ae5 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/complex.c @@ -0,0 +1,147 @@ +void complex_literals(void) { + _Complex float cf = 2.0; + cf = __I__; + _Complex double cd = 3.0; + cd = __I__; + _Complex long double cld = 5.0; + cld = __I__; + + _Imaginary float jf = __I__; + _Imaginary double jd = __I__; + _Imaginary long double jld = __I__; +} + +void complex_arithmetic(void) { + float f1 = 5.0; + float f2 = 7.0; + float f3; + _Complex float cf1 = 2.0; + _Complex float cf2 = __I__; + _Complex float cf3; + _Imaginary float jf1 = __I__; + _Imaginary float jf2 = __I__; + _Imaginary float jf3; + + // unaryop _Complex + cf3 = +cf1; + cf3 = -cf1; + + // _Complex binaryop _Complex + cf3 = cf1 + cf2; + cf3 = cf1 - cf2; + cf3 = cf1 * cf2; + cf3 = cf1 / cf2; + + // unaryop _Imaginary + jf3 = +jf1; + jf3 = -jf1; + + // _Imaginary binaryop _Imaginary + jf3 = jf1 + jf2; + jf3 = jf1 - jf2; + f3 = jf1 * jf2; // Result is _Real + f3 = jf1 / jf2; // Result is _Real + + // _Imaginary binaryop _Real + cf3 = jf1 + f2; + cf3 = jf1 - f2; + jf3 = jf1 * f2; // Result is _Imaginary + jf3 = jf1 / f2; // Result is _Imaginary + + // _Real binaryop _Imaginary + cf3 = f1 + jf2; + cf3 = f1 - jf2; + jf3 = f1 * jf2; // Result is _Imaginary + jf3 = f1 / jf2; // Result is _Imaginary +} + +void complex_conversions(void) { + float f = 2.0; + double d = 3.0; + long double ld = 5.0; + _Complex float cf = 7.0; + _Complex double cd = 11.0; + _Complex long double cld = 13.0; + _Imaginary float jf = __I__; + _Imaginary double jd = __I__; + _Imaginary long double jld = __I__; + + // _Complex to _Complex + cf = cf; + cf = cd; + cf = cld; + cd = cf; + cd = cd; + cd = cld; + cld = cf; + cld = cd; + cld = cld; + + // _Real to _Complex + cf = f; + cf = d; + cf = ld; + cd = f; + cd = d; + cd = ld; + cld = f; + cld = d; + cld = ld; + + // _Complex to _Real + f = cf; + f = cd; + f = cld; + d = cf; + d = cd; + d = cld; + ld = cf; + ld = cd; + ld = cld; + + // _Imaginary to _Complex + cf = jf; + cf = jd; + cf = jld; + cd = jf; + cd = jd; + cd = jld; + cld = jf; + cld = jd; + cld = jld; + + // _Complex to _Imaginary + jf = cf; + jf = cd; + jf = cld; + jd = cf; + jd = cd; + jd = cld; + jld = cf; + jld = cd; + jld = cld; + + // _Real to _Imaginary + jf = f; + jf = d; + jf = ld; + jd = f; + jd = d; + jd = ld; + jld = f; + jld = d; + jld = ld; + + // _Imaginary to _Real + f = jf; + f = jd; + f = jld; + d = jf; + d = jd; + d = jld; + ld = jf; + ld = jd; + ld = jld; +} + +// semmle-extractor-options: --microsoft --edg --c99 diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index c1c1e55145b..cdebee29aea 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1243,4 +1243,57 @@ void staticLocalWithConstructor(const char* dynamic) { static String c(dynamic); } +// --- strings --- + +char *strcpy(char *destination, const char *source); +char *strcat(char *destination, const char *source); + +void test_strings(char *s1, char *s2) { + char buffer[1024] = {0}; + + strcpy(buffer, s1); + strcat(buffer, s2); +} + +struct A { + int member; + + static void static_member(A* a, int x) { + a->member = x; + } + + static void static_member_without_def(); +}; + +A* getAnInstanceOfA(); + +void test_static_member_functions(int int_arg, A* a_arg) { + C c; + c.StaticMemberFunction(10); + C::StaticMemberFunction(10); + + A a; + a.static_member(&a, int_arg); + A::static_member(&a, int_arg); + + (&a)->static_member(a_arg, int_arg + 2); + (*a_arg).static_member(&a, 99); + a_arg->static_member(a_arg, -1); + + a.static_member_without_def(); + A::static_member_without_def(); + + getAnInstanceOfA()->static_member_without_def(); +} + +int missingReturnValue(bool b, int x) { + if (b) { + return x; + } +} + +void returnVoid(int x, int y) { + return IntegerOps(x, y); +} + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index e4bbac446ba..b5f57acaa4c 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -69,7 +69,7 @@ bad_asts.cpp: # 26| mu26_4(unknown) = UnmodeledDefinition : # 26| r26_5(glval) = VariableAddress[a] : # 26| mu26_6(Point &) = InitializeParameter[a] : &:r26_5 -# 26| r26_7(Point &) = Load : &:r26_5, ~mu26_6 +# 26| r26_7(Point &) = Load : &:r26_5, ~mu26_4 # 26| mu26_8(unknown) = InitializeIndirection[a] : &:r26_7 # 27| r27_1(glval) = VariableAddress[b] : # 27| r27_2(glval) = VariableAddress[a] : @@ -79,7 +79,7 @@ bad_asts.cpp: # 27| r27_6(Point) = Load : &:r27_5, ~mu26_4 # 27| mu27_7(Point) = Store : &:r27_1, r27_6 # 28| v28_1(void) = NoOp : -# 26| v26_9(void) = ReturnIndirection : &:r26_7, ~mu26_4 +# 26| v26_9(void) = ReturnIndirection[a] : &:r26_7, ~mu26_4 # 26| v26_10(void) = ReturnVoid : # 26| v26_11(void) = UnmodeledUse : mu* # 26| v26_12(void) = AliasedUse : ~mu26_4 @@ -124,6 +124,580 @@ clang.cpp: # 5| v5_8(void) = AliasedUse : ~mu5_4 # 5| v5_9(void) = ExitFunction : +complex.c: +# 1| void complex_literals() +# 1| Block 0 +# 1| v1_1(void) = EnterFunction : +# 1| mu1_2(unknown) = AliasedDefinition : +# 1| mu1_3(unknown) = InitializeNonLocal : +# 1| mu1_4(unknown) = UnmodeledDefinition : +# 2| r2_1(glval<_Complex float>) = VariableAddress[cf] : +# 2| r2_2(double) = Constant[2.0] : +# 2| r2_3(_Complex float) = Convert : r2_2 +# 2| mu2_4(_Complex float) = Store : &:r2_1, r2_3 +# 3| r3_1(_Imaginary float) = Constant[1.0i] : +# 3| r3_2(_Complex float) = Convert : r3_1 +# 3| r3_3(glval<_Complex float>) = VariableAddress[cf] : +# 3| mu3_4(_Complex float) = Store : &:r3_3, r3_2 +# 4| r4_1(glval<_Complex double>) = VariableAddress[cd] : +# 4| r4_2(double) = Constant[3.0] : +# 4| r4_3(_Complex double) = Convert : r4_2 +# 4| mu4_4(_Complex double) = Store : &:r4_1, r4_3 +# 5| r5_1(_Imaginary float) = Constant[1.0i] : +# 5| r5_2(_Complex double) = Convert : r5_1 +# 5| r5_3(glval<_Complex double>) = VariableAddress[cd] : +# 5| mu5_4(_Complex double) = Store : &:r5_3, r5_2 +# 6| r6_1(glval<_Complex long double>) = VariableAddress[cld] : +# 6| r6_2(double) = Constant[5.0] : +# 6| r6_3(_Complex long double) = Convert : r6_2 +# 6| mu6_4(_Complex long double) = Store : &:r6_1, r6_3 +# 7| r7_1(_Imaginary float) = Constant[1.0i] : +# 7| r7_2(_Complex long double) = Convert : r7_1 +# 7| r7_3(glval<_Complex long double>) = VariableAddress[cld] : +# 7| mu7_4(_Complex long double) = Store : &:r7_3, r7_2 +# 9| r9_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 9| r9_2(_Imaginary float) = Constant[1.0i] : +# 9| mu9_3(_Imaginary float) = Store : &:r9_1, r9_2 +# 10| r10_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 10| r10_2(_Imaginary float) = Constant[1.0i] : +# 10| r10_3(_Imaginary double) = Convert : r10_2 +# 10| mu10_4(_Imaginary double) = Store : &:r10_1, r10_3 +# 11| r11_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 11| r11_2(_Imaginary float) = Constant[1.0i] : +# 11| r11_3(_Imaginary long double) = Convert : r11_2 +# 11| mu11_4(_Imaginary long double) = Store : &:r11_1, r11_3 +# 12| v12_1(void) = NoOp : +# 1| v1_5(void) = ReturnVoid : +# 1| v1_6(void) = UnmodeledUse : mu* +# 1| v1_7(void) = AliasedUse : ~mu1_4 +# 1| v1_8(void) = ExitFunction : + +# 14| void complex_arithmetic() +# 14| Block 0 +# 14| v14_1(void) = EnterFunction : +# 14| mu14_2(unknown) = AliasedDefinition : +# 14| mu14_3(unknown) = InitializeNonLocal : +# 14| mu14_4(unknown) = UnmodeledDefinition : +# 15| r15_1(glval) = VariableAddress[f1] : +# 15| r15_2(float) = Constant[5.0] : +# 15| mu15_3(float) = Store : &:r15_1, r15_2 +# 16| r16_1(glval) = VariableAddress[f2] : +# 16| r16_2(float) = Constant[7.0] : +# 16| mu16_3(float) = Store : &:r16_1, r16_2 +# 17| r17_1(glval) = VariableAddress[f3] : +# 17| mu17_2(float) = Uninitialized[f3] : &:r17_1 +# 18| r18_1(glval<_Complex float>) = VariableAddress[cf1] : +# 18| r18_2(double) = Constant[2.0] : +# 18| r18_3(_Complex float) = Convert : r18_2 +# 18| mu18_4(_Complex float) = Store : &:r18_1, r18_3 +# 19| r19_1(glval<_Complex float>) = VariableAddress[cf2] : +# 19| r19_2(_Imaginary float) = Constant[1.0i] : +# 19| r19_3(_Complex float) = Convert : r19_2 +# 19| mu19_4(_Complex float) = Store : &:r19_1, r19_3 +# 20| r20_1(glval<_Complex float>) = VariableAddress[cf3] : +# 20| mu20_2(_Complex float) = Uninitialized[cf3] : &:r20_1 +# 21| r21_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 21| r21_2(_Imaginary float) = Constant[1.0i] : +# 21| mu21_3(_Imaginary float) = Store : &:r21_1, r21_2 +# 22| r22_1(glval<_Imaginary float>) = VariableAddress[jf2] : +# 22| r22_2(_Imaginary float) = Constant[1.0i] : +# 22| mu22_3(_Imaginary float) = Store : &:r22_1, r22_2 +# 23| r23_1(glval<_Imaginary float>) = VariableAddress[jf3] : +# 23| mu23_2(_Imaginary float) = Uninitialized[jf3] : &:r23_1 +# 26| r26_1(glval<_Complex float>) = VariableAddress[cf1] : +# 26| r26_2(_Complex float) = Load : &:r26_1, ~mu14_4 +# 26| r26_3(_Complex float) = CopyValue : r26_2 +# 26| r26_4(glval<_Complex float>) = VariableAddress[cf3] : +# 26| mu26_5(_Complex float) = Store : &:r26_4, r26_3 +# 27| r27_1(glval<_Complex float>) = VariableAddress[cf1] : +# 27| r27_2(_Complex float) = Load : &:r27_1, ~mu14_4 +# 27| r27_3(_Complex float) = Negate : r27_2 +# 27| r27_4(glval<_Complex float>) = VariableAddress[cf3] : +# 27| mu27_5(_Complex float) = Store : &:r27_4, r27_3 +# 30| r30_1(glval<_Complex float>) = VariableAddress[cf1] : +# 30| r30_2(_Complex float) = Load : &:r30_1, ~mu14_4 +# 30| r30_3(glval<_Complex float>) = VariableAddress[cf2] : +# 30| r30_4(_Complex float) = Load : &:r30_3, ~mu14_4 +# 30| r30_5(_Complex float) = Add : r30_2, r30_4 +# 30| r30_6(glval<_Complex float>) = VariableAddress[cf3] : +# 30| mu30_7(_Complex float) = Store : &:r30_6, r30_5 +# 31| r31_1(glval<_Complex float>) = VariableAddress[cf1] : +# 31| r31_2(_Complex float) = Load : &:r31_1, ~mu14_4 +# 31| r31_3(glval<_Complex float>) = VariableAddress[cf2] : +# 31| r31_4(_Complex float) = Load : &:r31_3, ~mu14_4 +# 31| r31_5(_Complex float) = Sub : r31_2, r31_4 +# 31| r31_6(glval<_Complex float>) = VariableAddress[cf3] : +# 31| mu31_7(_Complex float) = Store : &:r31_6, r31_5 +# 32| r32_1(glval<_Complex float>) = VariableAddress[cf1] : +# 32| r32_2(_Complex float) = Load : &:r32_1, ~mu14_4 +# 32| r32_3(glval<_Complex float>) = VariableAddress[cf2] : +# 32| r32_4(_Complex float) = Load : &:r32_3, ~mu14_4 +# 32| r32_5(_Complex float) = Mul : r32_2, r32_4 +# 32| r32_6(glval<_Complex float>) = VariableAddress[cf3] : +# 32| mu32_7(_Complex float) = Store : &:r32_6, r32_5 +# 33| r33_1(glval<_Complex float>) = VariableAddress[cf1] : +# 33| r33_2(_Complex float) = Load : &:r33_1, ~mu14_4 +# 33| r33_3(glval<_Complex float>) = VariableAddress[cf2] : +# 33| r33_4(_Complex float) = Load : &:r33_3, ~mu14_4 +# 33| r33_5(_Complex float) = Div : r33_2, r33_4 +# 33| r33_6(glval<_Complex float>) = VariableAddress[cf3] : +# 33| mu33_7(_Complex float) = Store : &:r33_6, r33_5 +# 36| r36_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 36| r36_2(_Imaginary float) = Load : &:r36_1, ~mu14_4 +# 36| r36_3(_Imaginary float) = CopyValue : r36_2 +# 36| r36_4(glval<_Imaginary float>) = VariableAddress[jf3] : +# 36| mu36_5(_Imaginary float) = Store : &:r36_4, r36_3 +# 37| r37_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 37| r37_2(_Imaginary float) = Load : &:r37_1, ~mu14_4 +# 37| r37_3(_Imaginary float) = Negate : r37_2 +# 37| r37_4(glval<_Imaginary float>) = VariableAddress[jf3] : +# 37| mu37_5(_Imaginary float) = Store : &:r37_4, r37_3 +# 40| r40_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 40| r40_2(_Imaginary float) = Load : &:r40_1, ~mu14_4 +# 40| r40_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 40| r40_4(_Imaginary float) = Load : &:r40_3, ~mu14_4 +# 40| r40_5(_Imaginary float) = Add : r40_2, r40_4 +# 40| r40_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 40| mu40_7(_Imaginary float) = Store : &:r40_6, r40_5 +# 41| r41_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 41| r41_2(_Imaginary float) = Load : &:r41_1, ~mu14_4 +# 41| r41_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 41| r41_4(_Imaginary float) = Load : &:r41_3, ~mu14_4 +# 41| r41_5(_Imaginary float) = Sub : r41_2, r41_4 +# 41| r41_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 41| mu41_7(_Imaginary float) = Store : &:r41_6, r41_5 +# 42| r42_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 42| r42_2(_Imaginary float) = Load : &:r42_1, ~mu14_4 +# 42| r42_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 42| r42_4(_Imaginary float) = Load : &:r42_3, ~mu14_4 +# 42| r42_5(float) = Mul : r42_2, r42_4 +# 42| r42_6(glval) = VariableAddress[f3] : +# 42| mu42_7(float) = Store : &:r42_6, r42_5 +# 43| r43_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 43| r43_2(_Imaginary float) = Load : &:r43_1, ~mu14_4 +# 43| r43_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 43| r43_4(_Imaginary float) = Load : &:r43_3, ~mu14_4 +# 43| r43_5(float) = Div : r43_2, r43_4 +# 43| r43_6(glval) = VariableAddress[f3] : +# 43| mu43_7(float) = Store : &:r43_6, r43_5 +# 46| r46_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 46| r46_2(_Imaginary float) = Load : &:r46_1, ~mu14_4 +# 46| r46_3(glval) = VariableAddress[f2] : +# 46| r46_4(float) = Load : &:r46_3, ~mu14_4 +# 46| r46_5(_Complex float) = Add : r46_2, r46_4 +# 46| r46_6(glval<_Complex float>) = VariableAddress[cf3] : +# 46| mu46_7(_Complex float) = Store : &:r46_6, r46_5 +# 47| r47_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 47| r47_2(_Imaginary float) = Load : &:r47_1, ~mu14_4 +# 47| r47_3(glval) = VariableAddress[f2] : +# 47| r47_4(float) = Load : &:r47_3, ~mu14_4 +# 47| r47_5(_Complex float) = Sub : r47_2, r47_4 +# 47| r47_6(glval<_Complex float>) = VariableAddress[cf3] : +# 47| mu47_7(_Complex float) = Store : &:r47_6, r47_5 +# 48| r48_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 48| r48_2(_Imaginary float) = Load : &:r48_1, ~mu14_4 +# 48| r48_3(glval) = VariableAddress[f2] : +# 48| r48_4(float) = Load : &:r48_3, ~mu14_4 +# 48| r48_5(_Imaginary float) = Mul : r48_2, r48_4 +# 48| r48_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 48| mu48_7(_Imaginary float) = Store : &:r48_6, r48_5 +# 49| r49_1(glval<_Imaginary float>) = VariableAddress[jf1] : +# 49| r49_2(_Imaginary float) = Load : &:r49_1, ~mu14_4 +# 49| r49_3(glval) = VariableAddress[f2] : +# 49| r49_4(float) = Load : &:r49_3, ~mu14_4 +# 49| r49_5(_Imaginary float) = Div : r49_2, r49_4 +# 49| r49_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 49| mu49_7(_Imaginary float) = Store : &:r49_6, r49_5 +# 52| r52_1(glval) = VariableAddress[f1] : +# 52| r52_2(float) = Load : &:r52_1, ~mu14_4 +# 52| r52_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 52| r52_4(_Imaginary float) = Load : &:r52_3, ~mu14_4 +# 52| r52_5(_Complex float) = Add : r52_2, r52_4 +# 52| r52_6(glval<_Complex float>) = VariableAddress[cf3] : +# 52| mu52_7(_Complex float) = Store : &:r52_6, r52_5 +# 53| r53_1(glval) = VariableAddress[f1] : +# 53| r53_2(float) = Load : &:r53_1, ~mu14_4 +# 53| r53_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 53| r53_4(_Imaginary float) = Load : &:r53_3, ~mu14_4 +# 53| r53_5(_Complex float) = Sub : r53_2, r53_4 +# 53| r53_6(glval<_Complex float>) = VariableAddress[cf3] : +# 53| mu53_7(_Complex float) = Store : &:r53_6, r53_5 +# 54| r54_1(glval) = VariableAddress[f1] : +# 54| r54_2(float) = Load : &:r54_1, ~mu14_4 +# 54| r54_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 54| r54_4(_Imaginary float) = Load : &:r54_3, ~mu14_4 +# 54| r54_5(_Imaginary float) = Mul : r54_2, r54_4 +# 54| r54_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 54| mu54_7(_Imaginary float) = Store : &:r54_6, r54_5 +# 55| r55_1(glval) = VariableAddress[f1] : +# 55| r55_2(float) = Load : &:r55_1, ~mu14_4 +# 55| r55_3(glval<_Imaginary float>) = VariableAddress[jf2] : +# 55| r55_4(_Imaginary float) = Load : &:r55_3, ~mu14_4 +# 55| r55_5(_Imaginary float) = Div : r55_2, r55_4 +# 55| r55_6(glval<_Imaginary float>) = VariableAddress[jf3] : +# 55| mu55_7(_Imaginary float) = Store : &:r55_6, r55_5 +# 56| v56_1(void) = NoOp : +# 14| v14_5(void) = ReturnVoid : +# 14| v14_6(void) = UnmodeledUse : mu* +# 14| v14_7(void) = AliasedUse : ~mu14_4 +# 14| v14_8(void) = ExitFunction : + +# 58| void complex_conversions() +# 58| Block 0 +# 58| v58_1(void) = EnterFunction : +# 58| mu58_2(unknown) = AliasedDefinition : +# 58| mu58_3(unknown) = InitializeNonLocal : +# 58| mu58_4(unknown) = UnmodeledDefinition : +# 59| r59_1(glval) = VariableAddress[f] : +# 59| r59_2(float) = Constant[2.0] : +# 59| mu59_3(float) = Store : &:r59_1, r59_2 +# 60| r60_1(glval) = VariableAddress[d] : +# 60| r60_2(double) = Constant[3.0] : +# 60| mu60_3(double) = Store : &:r60_1, r60_2 +# 61| r61_1(glval) = VariableAddress[ld] : +# 61| r61_2(long double) = Constant[5.0] : +# 61| mu61_3(long double) = Store : &:r61_1, r61_2 +# 62| r62_1(glval<_Complex float>) = VariableAddress[cf] : +# 62| r62_2(double) = Constant[7.0] : +# 62| r62_3(_Complex float) = Convert : r62_2 +# 62| mu62_4(_Complex float) = Store : &:r62_1, r62_3 +# 63| r63_1(glval<_Complex double>) = VariableAddress[cd] : +# 63| r63_2(double) = Constant[11.0] : +# 63| r63_3(_Complex double) = Convert : r63_2 +# 63| mu63_4(_Complex double) = Store : &:r63_1, r63_3 +# 64| r64_1(glval<_Complex long double>) = VariableAddress[cld] : +# 64| r64_2(double) = Constant[13.0] : +# 64| r64_3(_Complex long double) = Convert : r64_2 +# 64| mu64_4(_Complex long double) = Store : &:r64_1, r64_3 +# 65| r65_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 65| r65_2(_Imaginary float) = Constant[1.0i] : +# 65| mu65_3(_Imaginary float) = Store : &:r65_1, r65_2 +# 66| r66_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 66| r66_2(_Imaginary float) = Constant[1.0i] : +# 66| r66_3(_Imaginary double) = Convert : r66_2 +# 66| mu66_4(_Imaginary double) = Store : &:r66_1, r66_3 +# 67| r67_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 67| r67_2(_Imaginary float) = Constant[1.0i] : +# 67| r67_3(_Imaginary long double) = Convert : r67_2 +# 67| mu67_4(_Imaginary long double) = Store : &:r67_1, r67_3 +# 70| r70_1(glval<_Complex float>) = VariableAddress[cf] : +# 70| r70_2(_Complex float) = Load : &:r70_1, ~mu58_4 +# 70| r70_3(glval<_Complex float>) = VariableAddress[cf] : +# 70| mu70_4(_Complex float) = Store : &:r70_3, r70_2 +# 71| r71_1(glval<_Complex double>) = VariableAddress[cd] : +# 71| r71_2(_Complex double) = Load : &:r71_1, ~mu58_4 +# 71| r71_3(_Complex float) = Convert : r71_2 +# 71| r71_4(glval<_Complex float>) = VariableAddress[cf] : +# 71| mu71_5(_Complex float) = Store : &:r71_4, r71_3 +# 72| r72_1(glval<_Complex long double>) = VariableAddress[cld] : +# 72| r72_2(_Complex long double) = Load : &:r72_1, ~mu58_4 +# 72| r72_3(_Complex float) = Convert : r72_2 +# 72| r72_4(glval<_Complex float>) = VariableAddress[cf] : +# 72| mu72_5(_Complex float) = Store : &:r72_4, r72_3 +# 73| r73_1(glval<_Complex float>) = VariableAddress[cf] : +# 73| r73_2(_Complex float) = Load : &:r73_1, ~mu58_4 +# 73| r73_3(_Complex double) = Convert : r73_2 +# 73| r73_4(glval<_Complex double>) = VariableAddress[cd] : +# 73| mu73_5(_Complex double) = Store : &:r73_4, r73_3 +# 74| r74_1(glval<_Complex double>) = VariableAddress[cd] : +# 74| r74_2(_Complex double) = Load : &:r74_1, ~mu58_4 +# 74| r74_3(glval<_Complex double>) = VariableAddress[cd] : +# 74| mu74_4(_Complex double) = Store : &:r74_3, r74_2 +# 75| r75_1(glval<_Complex long double>) = VariableAddress[cld] : +# 75| r75_2(_Complex long double) = Load : &:r75_1, ~mu58_4 +# 75| r75_3(_Complex double) = Convert : r75_2 +# 75| r75_4(glval<_Complex double>) = VariableAddress[cd] : +# 75| mu75_5(_Complex double) = Store : &:r75_4, r75_3 +# 76| r76_1(glval<_Complex float>) = VariableAddress[cf] : +# 76| r76_2(_Complex float) = Load : &:r76_1, ~mu58_4 +# 76| r76_3(_Complex long double) = Convert : r76_2 +# 76| r76_4(glval<_Complex long double>) = VariableAddress[cld] : +# 76| mu76_5(_Complex long double) = Store : &:r76_4, r76_3 +# 77| r77_1(glval<_Complex double>) = VariableAddress[cd] : +# 77| r77_2(_Complex double) = Load : &:r77_1, ~mu58_4 +# 77| r77_3(_Complex long double) = Convert : r77_2 +# 77| r77_4(glval<_Complex long double>) = VariableAddress[cld] : +# 77| mu77_5(_Complex long double) = Store : &:r77_4, r77_3 +# 78| r78_1(glval<_Complex long double>) = VariableAddress[cld] : +# 78| r78_2(_Complex long double) = Load : &:r78_1, ~mu58_4 +# 78| r78_3(glval<_Complex long double>) = VariableAddress[cld] : +# 78| mu78_4(_Complex long double) = Store : &:r78_3, r78_2 +# 81| r81_1(glval) = VariableAddress[f] : +# 81| r81_2(float) = Load : &:r81_1, ~mu58_4 +# 81| r81_3(_Complex float) = Convert : r81_2 +# 81| r81_4(glval<_Complex float>) = VariableAddress[cf] : +# 81| mu81_5(_Complex float) = Store : &:r81_4, r81_3 +# 82| r82_1(glval) = VariableAddress[d] : +# 82| r82_2(double) = Load : &:r82_1, ~mu58_4 +# 82| r82_3(_Complex float) = Convert : r82_2 +# 82| r82_4(glval<_Complex float>) = VariableAddress[cf] : +# 82| mu82_5(_Complex float) = Store : &:r82_4, r82_3 +# 83| r83_1(glval) = VariableAddress[ld] : +# 83| r83_2(long double) = Load : &:r83_1, ~mu58_4 +# 83| r83_3(_Complex float) = Convert : r83_2 +# 83| r83_4(glval<_Complex float>) = VariableAddress[cf] : +# 83| mu83_5(_Complex float) = Store : &:r83_4, r83_3 +# 84| r84_1(glval) = VariableAddress[f] : +# 84| r84_2(float) = Load : &:r84_1, ~mu58_4 +# 84| r84_3(_Complex double) = Convert : r84_2 +# 84| r84_4(glval<_Complex double>) = VariableAddress[cd] : +# 84| mu84_5(_Complex double) = Store : &:r84_4, r84_3 +# 85| r85_1(glval) = VariableAddress[d] : +# 85| r85_2(double) = Load : &:r85_1, ~mu58_4 +# 85| r85_3(_Complex double) = Convert : r85_2 +# 85| r85_4(glval<_Complex double>) = VariableAddress[cd] : +# 85| mu85_5(_Complex double) = Store : &:r85_4, r85_3 +# 86| r86_1(glval) = VariableAddress[ld] : +# 86| r86_2(long double) = Load : &:r86_1, ~mu58_4 +# 86| r86_3(_Complex double) = Convert : r86_2 +# 86| r86_4(glval<_Complex double>) = VariableAddress[cd] : +# 86| mu86_5(_Complex double) = Store : &:r86_4, r86_3 +# 87| r87_1(glval) = VariableAddress[f] : +# 87| r87_2(float) = Load : &:r87_1, ~mu58_4 +# 87| r87_3(_Complex long double) = Convert : r87_2 +# 87| r87_4(glval<_Complex long double>) = VariableAddress[cld] : +# 87| mu87_5(_Complex long double) = Store : &:r87_4, r87_3 +# 88| r88_1(glval) = VariableAddress[d] : +# 88| r88_2(double) = Load : &:r88_1, ~mu58_4 +# 88| r88_3(_Complex long double) = Convert : r88_2 +# 88| r88_4(glval<_Complex long double>) = VariableAddress[cld] : +# 88| mu88_5(_Complex long double) = Store : &:r88_4, r88_3 +# 89| r89_1(glval) = VariableAddress[ld] : +# 89| r89_2(long double) = Load : &:r89_1, ~mu58_4 +# 89| r89_3(_Complex long double) = Convert : r89_2 +# 89| r89_4(glval<_Complex long double>) = VariableAddress[cld] : +# 89| mu89_5(_Complex long double) = Store : &:r89_4, r89_3 +# 92| r92_1(glval<_Complex float>) = VariableAddress[cf] : +# 92| r92_2(_Complex float) = Load : &:r92_1, ~mu58_4 +# 92| r92_3(float) = Convert : r92_2 +# 92| r92_4(glval) = VariableAddress[f] : +# 92| mu92_5(float) = Store : &:r92_4, r92_3 +# 93| r93_1(glval<_Complex double>) = VariableAddress[cd] : +# 93| r93_2(_Complex double) = Load : &:r93_1, ~mu58_4 +# 93| r93_3(float) = Convert : r93_2 +# 93| r93_4(glval) = VariableAddress[f] : +# 93| mu93_5(float) = Store : &:r93_4, r93_3 +# 94| r94_1(glval<_Complex long double>) = VariableAddress[cld] : +# 94| r94_2(_Complex long double) = Load : &:r94_1, ~mu58_4 +# 94| r94_3(float) = Convert : r94_2 +# 94| r94_4(glval) = VariableAddress[f] : +# 94| mu94_5(float) = Store : &:r94_4, r94_3 +# 95| r95_1(glval<_Complex float>) = VariableAddress[cf] : +# 95| r95_2(_Complex float) = Load : &:r95_1, ~mu58_4 +# 95| r95_3(double) = Convert : r95_2 +# 95| r95_4(glval) = VariableAddress[d] : +# 95| mu95_5(double) = Store : &:r95_4, r95_3 +# 96| r96_1(glval<_Complex double>) = VariableAddress[cd] : +# 96| r96_2(_Complex double) = Load : &:r96_1, ~mu58_4 +# 96| r96_3(double) = Convert : r96_2 +# 96| r96_4(glval) = VariableAddress[d] : +# 96| mu96_5(double) = Store : &:r96_4, r96_3 +# 97| r97_1(glval<_Complex long double>) = VariableAddress[cld] : +# 97| r97_2(_Complex long double) = Load : &:r97_1, ~mu58_4 +# 97| r97_3(double) = Convert : r97_2 +# 97| r97_4(glval) = VariableAddress[d] : +# 97| mu97_5(double) = Store : &:r97_4, r97_3 +# 98| r98_1(glval<_Complex float>) = VariableAddress[cf] : +# 98| r98_2(_Complex float) = Load : &:r98_1, ~mu58_4 +# 98| r98_3(long double) = Convert : r98_2 +# 98| r98_4(glval) = VariableAddress[ld] : +# 98| mu98_5(long double) = Store : &:r98_4, r98_3 +# 99| r99_1(glval<_Complex double>) = VariableAddress[cd] : +# 99| r99_2(_Complex double) = Load : &:r99_1, ~mu58_4 +# 99| r99_3(long double) = Convert : r99_2 +# 99| r99_4(glval) = VariableAddress[ld] : +# 99| mu99_5(long double) = Store : &:r99_4, r99_3 +# 100| r100_1(glval<_Complex long double>) = VariableAddress[cld] : +# 100| r100_2(_Complex long double) = Load : &:r100_1, ~mu58_4 +# 100| r100_3(long double) = Convert : r100_2 +# 100| r100_4(glval) = VariableAddress[ld] : +# 100| mu100_5(long double) = Store : &:r100_4, r100_3 +# 103| r103_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 103| r103_2(_Imaginary float) = Load : &:r103_1, ~mu58_4 +# 103| r103_3(_Complex float) = Convert : r103_2 +# 103| r103_4(glval<_Complex float>) = VariableAddress[cf] : +# 103| mu103_5(_Complex float) = Store : &:r103_4, r103_3 +# 104| r104_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 104| r104_2(_Imaginary double) = Load : &:r104_1, ~mu58_4 +# 104| r104_3(_Complex float) = Convert : r104_2 +# 104| r104_4(glval<_Complex float>) = VariableAddress[cf] : +# 104| mu104_5(_Complex float) = Store : &:r104_4, r104_3 +# 105| r105_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 105| r105_2(_Imaginary long double) = Load : &:r105_1, ~mu58_4 +# 105| r105_3(_Complex float) = Convert : r105_2 +# 105| r105_4(glval<_Complex float>) = VariableAddress[cf] : +# 105| mu105_5(_Complex float) = Store : &:r105_4, r105_3 +# 106| r106_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 106| r106_2(_Imaginary float) = Load : &:r106_1, ~mu58_4 +# 106| r106_3(_Complex double) = Convert : r106_2 +# 106| r106_4(glval<_Complex double>) = VariableAddress[cd] : +# 106| mu106_5(_Complex double) = Store : &:r106_4, r106_3 +# 107| r107_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 107| r107_2(_Imaginary double) = Load : &:r107_1, ~mu58_4 +# 107| r107_3(_Complex double) = Convert : r107_2 +# 107| r107_4(glval<_Complex double>) = VariableAddress[cd] : +# 107| mu107_5(_Complex double) = Store : &:r107_4, r107_3 +# 108| r108_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 108| r108_2(_Imaginary long double) = Load : &:r108_1, ~mu58_4 +# 108| r108_3(_Complex double) = Convert : r108_2 +# 108| r108_4(glval<_Complex double>) = VariableAddress[cd] : +# 108| mu108_5(_Complex double) = Store : &:r108_4, r108_3 +# 109| r109_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 109| r109_2(_Imaginary float) = Load : &:r109_1, ~mu58_4 +# 109| r109_3(_Complex long double) = Convert : r109_2 +# 109| r109_4(glval<_Complex long double>) = VariableAddress[cld] : +# 109| mu109_5(_Complex long double) = Store : &:r109_4, r109_3 +# 110| r110_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 110| r110_2(_Imaginary double) = Load : &:r110_1, ~mu58_4 +# 110| r110_3(_Complex long double) = Convert : r110_2 +# 110| r110_4(glval<_Complex long double>) = VariableAddress[cld] : +# 110| mu110_5(_Complex long double) = Store : &:r110_4, r110_3 +# 111| r111_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 111| r111_2(_Imaginary long double) = Load : &:r111_1, ~mu58_4 +# 111| r111_3(_Complex long double) = Convert : r111_2 +# 111| r111_4(glval<_Complex long double>) = VariableAddress[cld] : +# 111| mu111_5(_Complex long double) = Store : &:r111_4, r111_3 +# 114| r114_1(glval<_Complex float>) = VariableAddress[cf] : +# 114| r114_2(_Complex float) = Load : &:r114_1, ~mu58_4 +# 114| r114_3(_Imaginary float) = Convert : r114_2 +# 114| r114_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 114| mu114_5(_Imaginary float) = Store : &:r114_4, r114_3 +# 115| r115_1(glval<_Complex double>) = VariableAddress[cd] : +# 115| r115_2(_Complex double) = Load : &:r115_1, ~mu58_4 +# 115| r115_3(_Imaginary float) = Convert : r115_2 +# 115| r115_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 115| mu115_5(_Imaginary float) = Store : &:r115_4, r115_3 +# 116| r116_1(glval<_Complex long double>) = VariableAddress[cld] : +# 116| r116_2(_Complex long double) = Load : &:r116_1, ~mu58_4 +# 116| r116_3(_Imaginary float) = Convert : r116_2 +# 116| r116_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 116| mu116_5(_Imaginary float) = Store : &:r116_4, r116_3 +# 117| r117_1(glval<_Complex float>) = VariableAddress[cf] : +# 117| r117_2(_Complex float) = Load : &:r117_1, ~mu58_4 +# 117| r117_3(_Imaginary double) = Convert : r117_2 +# 117| r117_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 117| mu117_5(_Imaginary double) = Store : &:r117_4, r117_3 +# 118| r118_1(glval<_Complex double>) = VariableAddress[cd] : +# 118| r118_2(_Complex double) = Load : &:r118_1, ~mu58_4 +# 118| r118_3(_Imaginary double) = Convert : r118_2 +# 118| r118_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 118| mu118_5(_Imaginary double) = Store : &:r118_4, r118_3 +# 119| r119_1(glval<_Complex long double>) = VariableAddress[cld] : +# 119| r119_2(_Complex long double) = Load : &:r119_1, ~mu58_4 +# 119| r119_3(_Imaginary double) = Convert : r119_2 +# 119| r119_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 119| mu119_5(_Imaginary double) = Store : &:r119_4, r119_3 +# 120| r120_1(glval<_Complex float>) = VariableAddress[cf] : +# 120| r120_2(_Complex float) = Load : &:r120_1, ~mu58_4 +# 120| r120_3(_Imaginary long double) = Convert : r120_2 +# 120| r120_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 120| mu120_5(_Imaginary long double) = Store : &:r120_4, r120_3 +# 121| r121_1(glval<_Complex double>) = VariableAddress[cd] : +# 121| r121_2(_Complex double) = Load : &:r121_1, ~mu58_4 +# 121| r121_3(_Imaginary long double) = Convert : r121_2 +# 121| r121_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 121| mu121_5(_Imaginary long double) = Store : &:r121_4, r121_3 +# 122| r122_1(glval<_Complex long double>) = VariableAddress[cld] : +# 122| r122_2(_Complex long double) = Load : &:r122_1, ~mu58_4 +# 122| r122_3(_Imaginary long double) = Convert : r122_2 +# 122| r122_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 122| mu122_5(_Imaginary long double) = Store : &:r122_4, r122_3 +# 125| r125_1(glval) = VariableAddress[f] : +# 125| r125_2(float) = Load : &:r125_1, ~mu58_4 +# 125| r125_3(_Imaginary float) = Convert : r125_2 +# 125| r125_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 125| mu125_5(_Imaginary float) = Store : &:r125_4, r125_3 +# 126| r126_1(glval) = VariableAddress[d] : +# 126| r126_2(double) = Load : &:r126_1, ~mu58_4 +# 126| r126_3(_Imaginary float) = Convert : r126_2 +# 126| r126_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 126| mu126_5(_Imaginary float) = Store : &:r126_4, r126_3 +# 127| r127_1(glval) = VariableAddress[ld] : +# 127| r127_2(long double) = Load : &:r127_1, ~mu58_4 +# 127| r127_3(_Imaginary float) = Convert : r127_2 +# 127| r127_4(glval<_Imaginary float>) = VariableAddress[jf] : +# 127| mu127_5(_Imaginary float) = Store : &:r127_4, r127_3 +# 128| r128_1(glval) = VariableAddress[f] : +# 128| r128_2(float) = Load : &:r128_1, ~mu58_4 +# 128| r128_3(_Imaginary double) = Convert : r128_2 +# 128| r128_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 128| mu128_5(_Imaginary double) = Store : &:r128_4, r128_3 +# 129| r129_1(glval) = VariableAddress[d] : +# 129| r129_2(double) = Load : &:r129_1, ~mu58_4 +# 129| r129_3(_Imaginary double) = Convert : r129_2 +# 129| r129_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 129| mu129_5(_Imaginary double) = Store : &:r129_4, r129_3 +# 130| r130_1(glval) = VariableAddress[ld] : +# 130| r130_2(long double) = Load : &:r130_1, ~mu58_4 +# 130| r130_3(_Imaginary double) = Convert : r130_2 +# 130| r130_4(glval<_Imaginary double>) = VariableAddress[jd] : +# 130| mu130_5(_Imaginary double) = Store : &:r130_4, r130_3 +# 131| r131_1(glval) = VariableAddress[f] : +# 131| r131_2(float) = Load : &:r131_1, ~mu58_4 +# 131| r131_3(_Imaginary long double) = Convert : r131_2 +# 131| r131_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 131| mu131_5(_Imaginary long double) = Store : &:r131_4, r131_3 +# 132| r132_1(glval) = VariableAddress[d] : +# 132| r132_2(double) = Load : &:r132_1, ~mu58_4 +# 132| r132_3(_Imaginary long double) = Convert : r132_2 +# 132| r132_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 132| mu132_5(_Imaginary long double) = Store : &:r132_4, r132_3 +# 133| r133_1(glval) = VariableAddress[ld] : +# 133| r133_2(long double) = Load : &:r133_1, ~mu58_4 +# 133| r133_3(_Imaginary long double) = Convert : r133_2 +# 133| r133_4(glval<_Imaginary long double>) = VariableAddress[jld] : +# 133| mu133_5(_Imaginary long double) = Store : &:r133_4, r133_3 +# 136| r136_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 136| r136_2(_Imaginary float) = Load : &:r136_1, ~mu58_4 +# 136| r136_3(float) = Convert : r136_2 +# 136| r136_4(glval) = VariableAddress[f] : +# 136| mu136_5(float) = Store : &:r136_4, r136_3 +# 137| r137_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 137| r137_2(_Imaginary double) = Load : &:r137_1, ~mu58_4 +# 137| r137_3(float) = Convert : r137_2 +# 137| r137_4(glval) = VariableAddress[f] : +# 137| mu137_5(float) = Store : &:r137_4, r137_3 +# 138| r138_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 138| r138_2(_Imaginary long double) = Load : &:r138_1, ~mu58_4 +# 138| r138_3(float) = Convert : r138_2 +# 138| r138_4(glval) = VariableAddress[f] : +# 138| mu138_5(float) = Store : &:r138_4, r138_3 +# 139| r139_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 139| r139_2(_Imaginary float) = Load : &:r139_1, ~mu58_4 +# 139| r139_3(double) = Convert : r139_2 +# 139| r139_4(glval) = VariableAddress[d] : +# 139| mu139_5(double) = Store : &:r139_4, r139_3 +# 140| r140_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 140| r140_2(_Imaginary double) = Load : &:r140_1, ~mu58_4 +# 140| r140_3(double) = Convert : r140_2 +# 140| r140_4(glval) = VariableAddress[d] : +# 140| mu140_5(double) = Store : &:r140_4, r140_3 +# 141| r141_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 141| r141_2(_Imaginary long double) = Load : &:r141_1, ~mu58_4 +# 141| r141_3(double) = Convert : r141_2 +# 141| r141_4(glval) = VariableAddress[d] : +# 141| mu141_5(double) = Store : &:r141_4, r141_3 +# 142| r142_1(glval<_Imaginary float>) = VariableAddress[jf] : +# 142| r142_2(_Imaginary float) = Load : &:r142_1, ~mu58_4 +# 142| r142_3(long double) = Convert : r142_2 +# 142| r142_4(glval) = VariableAddress[ld] : +# 142| mu142_5(long double) = Store : &:r142_4, r142_3 +# 143| r143_1(glval<_Imaginary double>) = VariableAddress[jd] : +# 143| r143_2(_Imaginary double) = Load : &:r143_1, ~mu58_4 +# 143| r143_3(long double) = Convert : r143_2 +# 143| r143_4(glval) = VariableAddress[ld] : +# 143| mu143_5(long double) = Store : &:r143_4, r143_3 +# 144| r144_1(glval<_Imaginary long double>) = VariableAddress[jld] : +# 144| r144_2(_Imaginary long double) = Load : &:r144_1, ~mu58_4 +# 144| r144_3(long double) = Convert : r144_2 +# 144| r144_4(glval) = VariableAddress[ld] : +# 144| mu144_5(long double) = Store : &:r144_4, r144_3 +# 145| v145_1(void) = NoOp : +# 58| v58_5(void) = ReturnVoid : +# 58| v58_6(void) = UnmodeledUse : mu* +# 58| v58_7(void) = AliasedUse : ~mu58_4 +# 58| v58_8(void) = ExitFunction : + ir.cpp: # 1| void Constants() # 1| Block 0 @@ -769,7 +1343,7 @@ ir.cpp: # 153| mu153_4(unknown) = UnmodeledDefinition : # 153| r153_5(glval) = VariableAddress[p] : # 153| mu153_6(int *) = InitializeParameter[p] : &:r153_5 -# 153| r153_7(int *) = Load : &:r153_5, ~mu153_6 +# 153| r153_7(int *) = Load : &:r153_5, ~mu153_4 # 153| mu153_8(unknown) = InitializeIndirection[p] : &:r153_7 # 153| r153_9(glval) = VariableAddress[i] : # 153| mu153_10(int) = InitializeParameter[i] : &:r153_9 @@ -836,7 +1410,7 @@ ir.cpp: # 168| r168_6(glval) = VariableAddress[b] : # 168| mu168_7(bool) = Store : &:r168_6, r168_5 # 169| v169_1(void) = NoOp : -# 153| v153_11(void) = ReturnIndirection : &:r153_7, ~mu153_4 +# 153| v153_11(void) = ReturnIndirection[p] : &:r153_7, ~mu153_4 # 153| v153_12(void) = ReturnVoid : # 153| v153_13(void) = UnmodeledUse : mu* # 153| v153_14(void) = AliasedUse : ~mu153_4 @@ -850,7 +1424,7 @@ ir.cpp: # 171| mu171_4(unknown) = UnmodeledDefinition : # 171| r171_5(glval) = VariableAddress[p] : # 171| mu171_6(int *) = InitializeParameter[p] : &:r171_5 -# 171| r171_7(int *) = Load : &:r171_5, ~mu171_6 +# 171| r171_7(int *) = Load : &:r171_5, ~mu171_4 # 171| mu171_8(unknown) = InitializeIndirection[p] : &:r171_7 # 171| r171_9(glval) = VariableAddress[i] : # 171| mu171_10(int) = InitializeParameter[i] : &:r171_9 @@ -923,7 +1497,7 @@ ir.cpp: # 184| r184_7(glval) = PointerAdd[4] : r184_4, r184_6 # 184| mu184_8(int) = Store : &:r184_7, r184_2 # 185| v185_1(void) = NoOp : -# 171| v171_11(void) = ReturnIndirection : &:r171_7, ~mu171_4 +# 171| v171_11(void) = ReturnIndirection[p] : &:r171_7, ~mu171_4 # 171| v171_12(void) = ReturnVoid : # 171| v171_13(void) = UnmodeledUse : mu* # 171| v171_14(void) = AliasedUse : ~mu171_4 @@ -972,11 +1546,11 @@ ir.cpp: # 193| mu193_4(unknown) = UnmodeledDefinition : # 193| r193_5(glval) = VariableAddress[p] : # 193| mu193_6(int *) = InitializeParameter[p] : &:r193_5 -# 193| r193_7(int *) = Load : &:r193_5, ~mu193_6 +# 193| r193_7(int *) = Load : &:r193_5, ~mu193_4 # 193| mu193_8(unknown) = InitializeIndirection[p] : &:r193_7 # 193| r193_9(glval) = VariableAddress[q] : # 193| mu193_10(int *) = InitializeParameter[q] : &:r193_9 -# 193| r193_11(int *) = Load : &:r193_9, ~mu193_10 +# 193| r193_11(int *) = Load : &:r193_9, ~mu193_4 # 193| mu193_12(unknown) = InitializeIndirection[q] : &:r193_11 # 194| r194_1(glval) = VariableAddress[b] : # 194| mu194_2(bool) = Uninitialized[b] : &:r194_1 @@ -1023,8 +1597,8 @@ ir.cpp: # 201| r201_6(glval) = VariableAddress[b] : # 201| mu201_7(bool) = Store : &:r201_6, r201_5 # 202| v202_1(void) = NoOp : -# 193| v193_13(void) = ReturnIndirection : &:r193_7, ~mu193_4 -# 193| v193_14(void) = ReturnIndirection : &:r193_11, ~mu193_4 +# 193| v193_13(void) = ReturnIndirection[p] : &:r193_7, ~mu193_4 +# 193| v193_14(void) = ReturnIndirection[q] : &:r193_11, ~mu193_4 # 193| v193_15(void) = ReturnVoid : # 193| v193_16(void) = UnmodeledUse : mu* # 193| v193_17(void) = AliasedUse : ~mu193_4 @@ -1038,7 +1612,7 @@ ir.cpp: # 204| mu204_4(unknown) = UnmodeledDefinition : # 204| r204_5(glval) = VariableAddress[p] : # 204| mu204_6(int *) = InitializeParameter[p] : &:r204_5 -# 204| r204_7(int *) = Load : &:r204_5, ~mu204_6 +# 204| r204_7(int *) = Load : &:r204_5, ~mu204_4 # 204| mu204_8(unknown) = InitializeIndirection[p] : &:r204_7 # 205| r205_1(glval) = VariableAddress[q] : # 205| mu205_2(int *) = Uninitialized[q] : &:r205_1 @@ -1073,7 +1647,7 @@ ir.cpp: # 210| r210_7(glval) = VariableAddress[q] : # 210| mu210_8(int *) = Store : &:r210_7, r210_6 # 211| v211_1(void) = NoOp : -# 204| v204_9(void) = ReturnIndirection : &:r204_7, ~mu204_4 +# 204| v204_9(void) = ReturnIndirection[p] : &:r204_7, ~mu204_4 # 204| v204_10(void) = ReturnVoid : # 204| v204_11(void) = UnmodeledUse : mu* # 204| v204_12(void) = AliasedUse : ~mu204_4 @@ -1672,7 +2246,7 @@ ir.cpp: # 341| mu341_4(unknown) = UnmodeledDefinition : # 341| r341_5(glval) = VariableAddress[p] : # 341| mu341_6(int *) = InitializeParameter[p] : &:r341_5 -# 341| r341_7(int *) = Load : &:r341_5, ~mu341_6 +# 341| r341_7(int *) = Load : &:r341_5, ~mu341_4 # 341| mu341_8(unknown) = InitializeIndirection[p] : &:r341_7 # 342| r342_1(int) = Constant[1] : # 342| r342_2(glval) = VariableAddress[p] : @@ -1684,7 +2258,7 @@ ir.cpp: # 343| r343_3(int *) = Load : &:r343_2, ~mu341_4 # 343| r343_4(int) = Load : &:r343_3, ~mu341_4 # 343| mu343_5(int) = Store : &:r343_1, r343_4 -# 341| v341_9(void) = ReturnIndirection : &:r341_7, ~mu341_4 +# 341| v341_9(void) = ReturnIndirection[p] : &:r341_7, ~mu341_4 # 341| r341_10(glval) = VariableAddress[#return] : # 341| v341_11(void) = ReturnValue : &:r341_10, ~mu341_4 # 341| v341_12(void) = UnmodeledUse : mu* @@ -2951,11 +3525,11 @@ ir.cpp: # 622| mu622_4(unknown) = UnmodeledDefinition : # 622| r622_5(glval) = VariableAddress[r] : # 622| mu622_6(String &) = InitializeParameter[r] : &:r622_5 -# 622| r622_7(String &) = Load : &:r622_5, ~mu622_6 +# 622| r622_7(String &) = Load : &:r622_5, ~mu622_4 # 622| mu622_8(unknown) = InitializeIndirection[r] : &:r622_7 # 622| r622_9(glval) = VariableAddress[p] : # 622| mu622_10(String *) = InitializeParameter[p] : &:r622_9 -# 622| r622_11(String *) = Load : &:r622_9, ~mu622_10 +# 622| r622_11(String *) = Load : &:r622_9, ~mu622_4 # 622| mu622_12(unknown) = InitializeIndirection[p] : &:r622_11 # 622| r622_13(glval) = VariableAddress[s] : # 622| mu622_14(String) = InitializeParameter[s] : &:r622_13 @@ -2984,13 +3558,34 @@ ir.cpp: # 625| v625_6(void) = ^BufferReadSideEffect[-1] : &:r625_2, ~mu622_4 # 625| mu625_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r625_2 # 626| v626_1(void) = NoOp : -# 622| v622_15(void) = ReturnIndirection : &:r622_7, ~mu622_4 -# 622| v622_16(void) = ReturnIndirection : &:r622_11, ~mu622_4 +# 622| v622_15(void) = ReturnIndirection[r] : &:r622_7, ~mu622_4 +# 622| v622_16(void) = ReturnIndirection[p] : &:r622_11, ~mu622_4 # 622| v622_17(void) = ReturnVoid : # 622| v622_18(void) = UnmodeledUse : mu* # 622| v622_19(void) = AliasedUse : ~mu622_4 # 622| v622_20(void) = ExitFunction : +# 628| void C::~C() +# 628| Block 0 +# 628| v628_1(void) = EnterFunction : +# 628| mu628_2(unknown) = AliasedDefinition : +# 628| mu628_3(unknown) = InitializeNonLocal : +# 628| mu628_4(unknown) = UnmodeledDefinition : +# 628| r628_5(glval) = InitializeThis : +#-----| v0_1(void) = NoOp : +# 628| r628_6(glval) = FieldAddress[m_f] : r628_5 +# 628| r628_7(glval) = FunctionAddress[~String] : +# 628| v628_8(void) = Call : func:r628_7, this:r628_6 +# 628| mu628_9(unknown) = ^CallSideEffect : ~mu628_4 +# 628| r628_10(glval) = FieldAddress[m_b] : r628_5 +# 628| r628_11(glval) = FunctionAddress[~String] : +# 628| v628_12(void) = Call : func:r628_11, this:r628_10 +# 628| mu628_13(unknown) = ^CallSideEffect : ~mu628_4 +# 628| v628_14(void) = ReturnVoid : +# 628| v628_15(void) = UnmodeledUse : mu* +# 628| v628_16(void) = AliasedUse : ~mu628_4 +# 628| v628_17(void) = ExitFunction : + # 630| int C::StaticMemberFunction(int) # 630| Block 0 # 630| v630_1(void) = EnterFunction : @@ -3170,14 +3765,14 @@ ir.cpp: # 675| mu675_4(unknown) = UnmodeledDefinition : # 675| r675_5(glval) = VariableAddress[r] : # 675| mu675_6(int &) = InitializeParameter[r] : &:r675_5 -# 675| r675_7(int &) = Load : &:r675_5, ~mu675_6 +# 675| r675_7(int &) = Load : &:r675_5, ~mu675_4 # 675| mu675_8(unknown) = InitializeIndirection[r] : &:r675_7 # 676| r676_1(glval) = VariableAddress[#return] : # 676| r676_2(glval) = VariableAddress[r] : # 676| r676_3(int &) = Load : &:r676_2, ~mu675_4 # 676| r676_4(int) = Load : &:r676_3, ~mu675_4 # 676| mu676_5(int) = Store : &:r676_1, r676_4 -# 675| v675_9(void) = ReturnIndirection : &:r675_7, ~mu675_4 +# 675| v675_9(void) = ReturnIndirection[r] : &:r675_7, ~mu675_4 # 675| r675_10(glval) = VariableAddress[#return] : # 675| v675_11(void) = ReturnValue : &:r675_10, ~mu675_4 # 675| v675_12(void) = UnmodeledUse : mu* @@ -3363,14 +3958,14 @@ ir.cpp: # 715| mu715_4(unknown) = UnmodeledDefinition : # 715| r715_5(glval) = VariableAddress[x] : # 715| mu715_6(void *) = InitializeParameter[x] : &:r715_5 -# 715| r715_7(void *) = Load : &:r715_5, ~mu715_6 +# 715| r715_7(void *) = Load : &:r715_5, ~mu715_4 # 715| mu715_8(unknown) = InitializeIndirection[x] : &:r715_7 # 715| r715_9(glval) = VariableAddress[y] : # 715| mu715_10(char) = InitializeParameter[y] : &:r715_9 # 716| r716_1(glval) = VariableAddress[#return] : # 716| r716_2(long) = Constant[0] : # 716| mu716_3(long) = Store : &:r716_1, r716_2 -# 715| v715_11(void) = ReturnIndirection : &:r715_7, ~mu715_4 +# 715| v715_11(void) = ReturnIndirection[x] : &:r715_7, ~mu715_4 # 715| r715_12(glval) = VariableAddress[#return] : # 715| v715_13(void) = ReturnValue : &:r715_12, ~mu715_4 # 715| v715_14(void) = UnmodeledUse : mu* @@ -3487,7 +4082,7 @@ ir.cpp: # 735| Block 10 # 735| r735_2(glval) = VariableAddress[s] : # 735| mu735_3(char *) = InitializeParameter[s] : &:r735_2 -# 735| r735_4(char *) = Load : &:r735_2, ~mu735_3 +# 735| r735_4(char *) = Load : &:r735_2, ~mu724_4 # 735| mu735_5(unknown) = InitializeIndirection[s] : &:r735_4 # 736| r736_1(glval) = VariableAddress[#throw736:5] : # 736| mu736_2(String) = Uninitialized[#throw736:5] : &:r736_1 @@ -3510,7 +4105,7 @@ ir.cpp: # 738| Block 12 # 738| r738_2(glval) = VariableAddress[e] : # 738| mu738_3(String &) = InitializeParameter[e] : &:r738_2 -# 738| r738_4(String &) = Load : &:r738_2, ~mu738_3 +# 738| r738_4(String &) = Load : &:r738_2, ~mu724_4 # 738| mu738_5(unknown) = InitializeIndirection[e] : &:r738_4 # 738| v738_6(void) = NoOp : #-----| Goto -> Block 14 @@ -3534,7 +4129,7 @@ ir.cpp: # 745| r745_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Base &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Base &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Base &) = Load : &:r0_1, ~mu745_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Base *) = CopyValue : r745_5 #-----| r0_6(glval) = FieldAddress[base_s] : r0_5 @@ -3557,7 +4152,7 @@ ir.cpp: #-----| r0_20(glval) = CopyValue : r0_19 #-----| r0_21(Base &) = CopyValue : r0_20 #-----| mu0_22(Base &) = Store : &:r0_18, r0_21 -#-----| v0_23(void) = ReturnIndirection : &:r0_3, ~mu745_4 +#-----| v0_23(void) = ReturnIndirection[p#0] : &:r0_3, ~mu745_4 # 745| r745_9(glval) = VariableAddress[#return] : # 745| v745_10(void) = ReturnValue : &:r745_9, ~mu745_4 # 745| v745_11(void) = UnmodeledUse : mu* @@ -3573,7 +4168,7 @@ ir.cpp: # 745| r745_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Base &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Base &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Base &) = Load : &:r0_1, ~mu745_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 # 745| r745_6(glval) = FieldAddress[base_s] : r745_5 # 745| r745_7(glval) = FunctionAddress[String] : @@ -3581,7 +4176,7 @@ ir.cpp: # 745| mu745_9(unknown) = ^CallSideEffect : ~mu745_4 # 745| mu745_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r745_6 # 745| v745_11(void) = NoOp : -#-----| v0_5(void) = ReturnIndirection : &:r0_3, ~mu745_4 +#-----| v0_5(void) = ReturnIndirection[p#0] : &:r0_3, ~mu745_4 # 745| v745_12(void) = ReturnVoid : # 745| v745_13(void) = UnmodeledUse : mu* # 745| v745_14(void) = AliasedUse : ~mu745_4 @@ -3631,7 +4226,7 @@ ir.cpp: # 754| r754_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Middle &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Middle &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Middle &) = Load : &:r0_1, ~mu754_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Middle *) = CopyValue : r754_5 #-----| r0_6(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_5 @@ -3671,7 +4266,7 @@ ir.cpp: #-----| r0_34(glval) = CopyValue : r0_33 #-----| r0_35(Middle &) = CopyValue : r0_34 #-----| mu0_36(Middle &) = Store : &:r0_32, r0_35 -#-----| v0_37(void) = ReturnIndirection : &:r0_3, ~mu754_4 +#-----| v0_37(void) = ReturnIndirection[p#0] : &:r0_3, ~mu754_4 # 754| r754_12(glval) = VariableAddress[#return] : # 754| v754_13(void) = ReturnValue : &:r754_12, ~mu754_4 # 754| v754_14(void) = UnmodeledUse : mu* @@ -3731,7 +4326,7 @@ ir.cpp: # 763| r763_5(glval) = InitializeThis : #-----| r0_1(glval) = VariableAddress[p#0] : #-----| mu0_2(Derived &) = InitializeParameter[p#0] : &:r0_1 -#-----| r0_3(Derived &) = Load : &:r0_1, ~mu0_2 +#-----| r0_3(Derived &) = Load : &:r0_1, ~mu763_4 #-----| mu0_4(unknown) = InitializeIndirection[p#0] : &:r0_3 #-----| r0_5(Derived *) = CopyValue : r763_5 #-----| r0_6(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_5 @@ -3771,7 +4366,7 @@ ir.cpp: #-----| r0_34(glval) = CopyValue : r0_33 #-----| r0_35(Derived &) = CopyValue : r0_34 #-----| mu0_36(Derived &) = Store : &:r0_32, r0_35 -#-----| v0_37(void) = ReturnIndirection : &:r0_3, ~mu763_4 +#-----| v0_37(void) = ReturnIndirection[p#0] : &:r0_3, ~mu763_4 # 763| r763_12(glval) = VariableAddress[#return] : # 763| v763_13(void) = ReturnValue : &:r763_12, ~mu763_4 # 763| v763_14(void) = UnmodeledUse : mu* @@ -4462,7 +5057,7 @@ ir.cpp: # 883| mu883_6(..(*)(..)) = InitializeParameter[pfn] : &:r883_5 # 883| r883_7(glval) = VariableAddress[p] : # 883| mu883_8(void *) = InitializeParameter[p] : &:r883_7 -# 883| r883_9(void *) = Load : &:r883_7, ~mu883_8 +# 883| r883_9(void *) = Load : &:r883_7, ~mu883_4 # 883| mu883_10(unknown) = InitializeIndirection[p] : &:r883_9 # 884| r884_1(glval<..(*)(..)>) = VariableAddress[pfn] : # 884| r884_2(..(*)(..)) = Load : &:r884_1, ~mu883_4 @@ -4475,7 +5070,7 @@ ir.cpp: # 885| r885_4(glval<..(*)(..)>) = VariableAddress[pfn] : # 885| mu885_5(..(*)(..)) = Store : &:r885_4, r885_3 # 886| v886_1(void) = NoOp : -# 883| v883_11(void) = ReturnIndirection : &:r883_9, ~mu883_4 +# 883| v883_11(void) = ReturnIndirection[p] : &:r883_9, ~mu883_4 # 883| v883_12(void) = ReturnVoid : # 883| v883_13(void) = UnmodeledUse : mu* # 883| v883_14(void) = AliasedUse : ~mu883_4 @@ -4491,7 +5086,7 @@ ir.cpp: # 888| mu888_6(int) = InitializeParameter[x] : &:r888_5 # 888| r888_7(glval<__va_list_tag *>) = VariableAddress[args] : # 888| mu888_8(__va_list_tag *) = InitializeParameter[args] : &:r888_7 -# 888| r888_9(__va_list_tag *) = Load : &:r888_7, ~mu888_8 +# 888| r888_9(__va_list_tag *) = Load : &:r888_7, ~mu888_4 # 888| mu888_10(unknown) = InitializeIndirection[args] : &:r888_9 # 889| r889_1(glval<__va_list_tag[1]>) = VariableAddress[args2] : # 889| mu889_2(__va_list_tag[1]) = Uninitialized[args2] : &:r889_1 @@ -4524,7 +5119,7 @@ ir.cpp: # 893| r893_2(__va_list_tag *) = Convert : r893_1 # 893| v893_3(void) = VarArgsEnd : r893_2 # 894| v894_1(void) = NoOp : -# 888| v888_11(void) = ReturnIndirection : &:r888_9, ~mu888_4 +# 888| v888_11(void) = ReturnIndirection[args] : &:r888_9, ~mu888_4 # 888| v888_12(void) = ReturnVoid : # 888| v888_13(void) = UnmodeledUse : mu* # 888| v888_14(void) = AliasedUse : ~mu888_4 @@ -4540,7 +5135,7 @@ ir.cpp: # 896| mu896_6(int) = InitializeParameter[x] : &:r896_5 # 896| r896_7(glval) = VariableAddress[#ellipsis] : # 896| mu896_8(unknown[11]) = InitializeParameter[#ellipsis] : &:r896_7 -# 896| r896_9(unknown[11]) = Load : &:r896_7, ~mu896_8 +# 896| r896_9(unknown[11]) = Load : &:r896_7, ~mu896_4 # 896| mu896_10(unknown) = InitializeIndirection[#ellipsis] : &:r896_9 # 897| r897_1(glval<__va_list_tag[1]>) = VariableAddress[args] : # 897| mu897_2(__va_list_tag[1]) = Uninitialized[args] : &:r897_1 @@ -4664,58 +5259,65 @@ ir.cpp: # 950| r950_2(unsigned long) = Constant[4] : # 950| r950_3(void *) = Call : func:r950_1, 0:r950_2 # 950| mu950_4(unknown) = ^CallSideEffect : ~mu949_4 -# 950| r950_5(int *) = Convert : r950_3 +# 950| mu950_5(unknown) = ^InitializeDynamicAllocation : &:r950_3 +# 950| r950_6(int *) = Convert : r950_3 # 951| r951_1(glval) = FunctionAddress[operator new] : # 951| r951_2(unsigned long) = Constant[4] : # 951| r951_3(float) = Constant[1.0] : # 951| r951_4(void *) = Call : func:r951_1, 0:r951_2, 1:r951_3 # 951| mu951_5(unknown) = ^CallSideEffect : ~mu949_4 -# 951| r951_6(int *) = Convert : r951_4 +# 951| mu951_6(unknown) = ^InitializeDynamicAllocation : &:r951_4 +# 951| r951_7(int *) = Convert : r951_4 # 952| r952_1(glval) = FunctionAddress[operator new] : # 952| r952_2(unsigned long) = Constant[4] : # 952| r952_3(void *) = Call : func:r952_1, 0:r952_2 # 952| mu952_4(unknown) = ^CallSideEffect : ~mu949_4 -# 952| r952_5(int *) = Convert : r952_3 -# 952| r952_6(int) = Constant[0] : -# 952| mu952_7(int) = Store : &:r952_5, r952_6 +# 952| mu952_5(unknown) = ^InitializeDynamicAllocation : &:r952_3 +# 952| r952_6(int *) = Convert : r952_3 +# 952| r952_7(int) = Constant[0] : +# 952| mu952_8(int) = Store : &:r952_6, r952_7 # 953| r953_1(glval) = FunctionAddress[operator new] : # 953| r953_2(unsigned long) = Constant[8] : # 953| r953_3(void *) = Call : func:r953_1, 0:r953_2 # 953| mu953_4(unknown) = ^CallSideEffect : ~mu949_4 -# 953| r953_5(String *) = Convert : r953_3 -# 953| r953_6(glval) = FunctionAddress[String] : -# 953| v953_7(void) = Call : func:r953_6, this:r953_5 -# 953| mu953_8(unknown) = ^CallSideEffect : ~mu949_4 -# 953| mu953_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r953_5 +# 953| mu953_5(unknown) = ^InitializeDynamicAllocation : &:r953_3 +# 953| r953_6(String *) = Convert : r953_3 +# 953| r953_7(glval) = FunctionAddress[String] : +# 953| v953_8(void) = Call : func:r953_7, this:r953_6 +# 953| mu953_9(unknown) = ^CallSideEffect : ~mu949_4 +# 953| mu953_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r953_6 # 954| r954_1(glval) = FunctionAddress[operator new] : # 954| r954_2(unsigned long) = Constant[8] : # 954| r954_3(float) = Constant[1.0] : # 954| r954_4(void *) = Call : func:r954_1, 0:r954_2, 1:r954_3 # 954| mu954_5(unknown) = ^CallSideEffect : ~mu949_4 -# 954| r954_6(String *) = Convert : r954_4 -# 954| r954_7(glval) = FunctionAddress[String] : -# 954| r954_8(glval) = StringConstant["hello"] : -# 954| r954_9(char *) = Convert : r954_8 -# 954| v954_10(void) = Call : func:r954_7, this:r954_6, 0:r954_9 -# 954| mu954_11(unknown) = ^CallSideEffect : ~mu949_4 -# 954| mu954_12(String) = ^IndirectMayWriteSideEffect[-1] : &:r954_6 -# 954| v954_13(void) = ^BufferReadSideEffect[0] : &:r954_9, ~mu949_4 -# 954| mu954_14(unknown) = ^BufferMayWriteSideEffect[0] : &:r954_9 +# 954| mu954_6(unknown) = ^InitializeDynamicAllocation : &:r954_4 +# 954| r954_7(String *) = Convert : r954_4 +# 954| r954_8(glval) = FunctionAddress[String] : +# 954| r954_9(glval) = StringConstant["hello"] : +# 954| r954_10(char *) = Convert : r954_9 +# 954| v954_11(void) = Call : func:r954_8, this:r954_7, 0:r954_10 +# 954| mu954_12(unknown) = ^CallSideEffect : ~mu949_4 +# 954| mu954_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r954_7 +# 954| v954_14(void) = ^BufferReadSideEffect[0] : &:r954_10, ~mu949_4 +# 954| mu954_15(unknown) = ^BufferMayWriteSideEffect[0] : &:r954_10 # 955| r955_1(glval) = FunctionAddress[operator new] : # 955| r955_2(unsigned long) = Constant[256] : # 955| r955_3(align_val_t) = Constant[128] : # 955| r955_4(void *) = Call : func:r955_1, 0:r955_2, 1:r955_3 # 955| mu955_5(unknown) = ^CallSideEffect : ~mu949_4 -# 955| r955_6(Overaligned *) = Convert : r955_4 +# 955| mu955_6(unknown) = ^InitializeDynamicAllocation : &:r955_4 +# 955| r955_7(Overaligned *) = Convert : r955_4 # 956| r956_1(glval) = FunctionAddress[operator new] : # 956| r956_2(unsigned long) = Constant[256] : # 956| r956_3(align_val_t) = Constant[128] : # 956| r956_4(float) = Constant[1.0] : # 956| r956_5(void *) = Call : func:r956_1, 0:r956_2, 1:r956_3, 2:r956_4 # 956| mu956_6(unknown) = ^CallSideEffect : ~mu949_4 -# 956| r956_7(Overaligned *) = Convert : r956_5 -# 956| r956_8(Overaligned) = Constant[0] : -# 956| mu956_9(Overaligned) = Store : &:r956_7, r956_8 +# 956| mu956_7(unknown) = ^InitializeDynamicAllocation : &:r956_5 +# 956| r956_8(Overaligned *) = Convert : r956_5 +# 956| r956_9(Overaligned) = Constant[0] : +# 956| mu956_10(Overaligned) = Store : &:r956_8, r956_9 # 957| v957_1(void) = NoOp : # 949| v949_5(void) = ReturnVoid : # 949| v949_6(void) = UnmodeledUse : mu* @@ -4724,85 +5326,93 @@ ir.cpp: # 959| void OperatorNewArray(int) # 959| Block 0 -# 959| v959_1(void) = EnterFunction : -# 959| mu959_2(unknown) = AliasedDefinition : -# 959| mu959_3(unknown) = InitializeNonLocal : -# 959| mu959_4(unknown) = UnmodeledDefinition : -# 959| r959_5(glval) = VariableAddress[n] : -# 959| mu959_6(int) = InitializeParameter[n] : &:r959_5 -# 960| r960_1(glval) = FunctionAddress[operator new[]] : -# 960| r960_2(unsigned long) = Constant[40] : -# 960| r960_3(void *) = Call : func:r960_1, 0:r960_2 -# 960| mu960_4(unknown) = ^CallSideEffect : ~mu959_4 -# 960| r960_5(int *) = Convert : r960_3 -# 961| r961_1(glval) = FunctionAddress[operator new[]] : -# 961| r961_2(glval) = VariableAddress[n] : -# 961| r961_3(int) = Load : &:r961_2, ~mu959_4 -# 961| r961_4(unsigned long) = Convert : r961_3 -# 961| r961_5(unsigned long) = Constant[4] : -# 961| r961_6(unsigned long) = Mul : r961_4, r961_5 -# 961| r961_7(void *) = Call : func:r961_1, 0:r961_6 -# 961| mu961_8(unknown) = ^CallSideEffect : ~mu959_4 -# 961| r961_9(int *) = Convert : r961_7 -# 962| r962_1(glval) = FunctionAddress[operator new[]] : -# 962| r962_2(glval) = VariableAddress[n] : -# 962| r962_3(int) = Load : &:r962_2, ~mu959_4 -# 962| r962_4(unsigned long) = Convert : r962_3 -# 962| r962_5(unsigned long) = Constant[4] : -# 962| r962_6(unsigned long) = Mul : r962_4, r962_5 -# 962| r962_7(float) = Constant[1.0] : -# 962| r962_8(void *) = Call : func:r962_1, 0:r962_6, 1:r962_7 -# 962| mu962_9(unknown) = ^CallSideEffect : ~mu959_4 -# 962| r962_10(int *) = Convert : r962_8 -# 963| r963_1(glval) = FunctionAddress[operator new[]] : -# 963| r963_2(glval) = VariableAddress[n] : -# 963| r963_3(int) = Load : &:r963_2, ~mu959_4 -# 963| r963_4(unsigned long) = Convert : r963_3 -# 963| r963_5(unsigned long) = Constant[8] : -# 963| r963_6(unsigned long) = Mul : r963_4, r963_5 -# 963| r963_7(void *) = Call : func:r963_1, 0:r963_6 -# 963| mu963_8(unknown) = ^CallSideEffect : ~mu959_4 -# 963| r963_9(String *) = Convert : r963_7 -# 964| r964_1(glval) = FunctionAddress[operator new[]] : -# 964| r964_2(glval) = VariableAddress[n] : -# 964| r964_3(int) = Load : &:r964_2, ~mu959_4 -# 964| r964_4(unsigned long) = Convert : r964_3 -# 964| r964_5(unsigned long) = Constant[256] : -# 964| r964_6(unsigned long) = Mul : r964_4, r964_5 -# 964| r964_7(align_val_t) = Constant[128] : -# 964| r964_8(void *) = Call : func:r964_1, 0:r964_6, 1:r964_7 -# 964| mu964_9(unknown) = ^CallSideEffect : ~mu959_4 -# 964| r964_10(Overaligned *) = Convert : r964_8 -# 965| r965_1(glval) = FunctionAddress[operator new[]] : -# 965| r965_2(unsigned long) = Constant[2560] : -# 965| r965_3(align_val_t) = Constant[128] : -# 965| r965_4(float) = Constant[1.0] : -# 965| r965_5(void *) = Call : func:r965_1, 0:r965_2, 1:r965_3, 2:r965_4 -# 965| mu965_6(unknown) = ^CallSideEffect : ~mu959_4 -# 965| r965_7(Overaligned *) = Convert : r965_5 -# 966| r966_1(glval) = FunctionAddress[operator new[]] : -# 966| r966_2(glval) = VariableAddress[n] : -# 966| r966_3(int) = Load : &:r966_2, ~mu959_4 -# 966| r966_4(unsigned long) = Convert : r966_3 -# 966| r966_5(unsigned long) = Constant[1] : -# 966| r966_6(unsigned long) = Mul : r966_4, r966_5 -# 966| r966_7(void *) = Call : func:r966_1, 0:r966_6 -# 966| mu966_8(unknown) = ^CallSideEffect : ~mu959_4 -# 966| r966_9(DefaultCtorWithDefaultParam *) = Convert : r966_7 -# 967| r967_1(glval) = FunctionAddress[operator new[]] : -# 967| r967_2(glval) = VariableAddress[n] : -# 967| r967_3(int) = Load : &:r967_2, ~mu959_4 -# 967| r967_4(unsigned long) = Convert : r967_3 -# 967| r967_5(unsigned long) = Constant[4] : -# 967| r967_6(unsigned long) = Mul : r967_4, r967_5 -# 967| r967_7(void *) = Call : func:r967_1, 0:r967_6 -# 967| mu967_8(unknown) = ^CallSideEffect : ~mu959_4 -# 967| r967_9(int *) = Convert : r967_7 -# 968| v968_1(void) = NoOp : -# 959| v959_7(void) = ReturnVoid : -# 959| v959_8(void) = UnmodeledUse : mu* -# 959| v959_9(void) = AliasedUse : ~mu959_4 -# 959| v959_10(void) = ExitFunction : +# 959| v959_1(void) = EnterFunction : +# 959| mu959_2(unknown) = AliasedDefinition : +# 959| mu959_3(unknown) = InitializeNonLocal : +# 959| mu959_4(unknown) = UnmodeledDefinition : +# 959| r959_5(glval) = VariableAddress[n] : +# 959| mu959_6(int) = InitializeParameter[n] : &:r959_5 +# 960| r960_1(glval) = FunctionAddress[operator new[]] : +# 960| r960_2(unsigned long) = Constant[40] : +# 960| r960_3(void *) = Call : func:r960_1, 0:r960_2 +# 960| mu960_4(unknown) = ^CallSideEffect : ~mu959_4 +# 960| mu960_5(unknown) = ^InitializeDynamicAllocation : &:r960_3 +# 960| r960_6(int *) = Convert : r960_3 +# 961| r961_1(glval) = FunctionAddress[operator new[]] : +# 961| r961_2(glval) = VariableAddress[n] : +# 961| r961_3(int) = Load : &:r961_2, ~mu959_4 +# 961| r961_4(unsigned long) = Convert : r961_3 +# 961| r961_5(unsigned long) = Constant[4] : +# 961| r961_6(unsigned long) = Mul : r961_4, r961_5 +# 961| r961_7(void *) = Call : func:r961_1, 0:r961_6 +# 961| mu961_8(unknown) = ^CallSideEffect : ~mu959_4 +# 961| mu961_9(unknown) = ^InitializeDynamicAllocation : &:r961_7 +# 961| r961_10(int *) = Convert : r961_7 +# 962| r962_1(glval) = FunctionAddress[operator new[]] : +# 962| r962_2(glval) = VariableAddress[n] : +# 962| r962_3(int) = Load : &:r962_2, ~mu959_4 +# 962| r962_4(unsigned long) = Convert : r962_3 +# 962| r962_5(unsigned long) = Constant[4] : +# 962| r962_6(unsigned long) = Mul : r962_4, r962_5 +# 962| r962_7(float) = Constant[1.0] : +# 962| r962_8(void *) = Call : func:r962_1, 0:r962_6, 1:r962_7 +# 962| mu962_9(unknown) = ^CallSideEffect : ~mu959_4 +# 962| mu962_10(unknown) = ^InitializeDynamicAllocation : &:r962_8 +# 962| r962_11(int *) = Convert : r962_8 +# 963| r963_1(glval) = FunctionAddress[operator new[]] : +# 963| r963_2(glval) = VariableAddress[n] : +# 963| r963_3(int) = Load : &:r963_2, ~mu959_4 +# 963| r963_4(unsigned long) = Convert : r963_3 +# 963| r963_5(unsigned long) = Constant[8] : +# 963| r963_6(unsigned long) = Mul : r963_4, r963_5 +# 963| r963_7(void *) = Call : func:r963_1, 0:r963_6 +# 963| mu963_8(unknown) = ^CallSideEffect : ~mu959_4 +# 963| mu963_9(unknown) = ^InitializeDynamicAllocation : &:r963_7 +# 963| r963_10(String *) = Convert : r963_7 +# 964| r964_1(glval) = FunctionAddress[operator new[]] : +# 964| r964_2(glval) = VariableAddress[n] : +# 964| r964_3(int) = Load : &:r964_2, ~mu959_4 +# 964| r964_4(unsigned long) = Convert : r964_3 +# 964| r964_5(unsigned long) = Constant[256] : +# 964| r964_6(unsigned long) = Mul : r964_4, r964_5 +# 964| r964_7(align_val_t) = Constant[128] : +# 964| r964_8(void *) = Call : func:r964_1, 0:r964_6, 1:r964_7 +# 964| mu964_9(unknown) = ^CallSideEffect : ~mu959_4 +# 964| mu964_10(unknown) = ^InitializeDynamicAllocation : &:r964_8 +# 964| r964_11(Overaligned *) = Convert : r964_8 +# 965| r965_1(glval) = FunctionAddress[operator new[]] : +# 965| r965_2(unsigned long) = Constant[2560] : +# 965| r965_3(align_val_t) = Constant[128] : +# 965| r965_4(float) = Constant[1.0] : +# 965| r965_5(void *) = Call : func:r965_1, 0:r965_2, 1:r965_3, 2:r965_4 +# 965| mu965_6(unknown) = ^CallSideEffect : ~mu959_4 +# 965| mu965_7(unknown) = ^InitializeDynamicAllocation : &:r965_5 +# 965| r965_8(Overaligned *) = Convert : r965_5 +# 966| r966_1(glval) = FunctionAddress[operator new[]] : +# 966| r966_2(glval) = VariableAddress[n] : +# 966| r966_3(int) = Load : &:r966_2, ~mu959_4 +# 966| r966_4(unsigned long) = Convert : r966_3 +# 966| r966_5(unsigned long) = Constant[1] : +# 966| r966_6(unsigned long) = Mul : r966_4, r966_5 +# 966| r966_7(void *) = Call : func:r966_1, 0:r966_6 +# 966| mu966_8(unknown) = ^CallSideEffect : ~mu959_4 +# 966| mu966_9(unknown) = ^InitializeDynamicAllocation : &:r966_7 +# 966| r966_10(DefaultCtorWithDefaultParam *) = Convert : r966_7 +# 967| r967_1(glval) = FunctionAddress[operator new[]] : +# 967| r967_2(glval) = VariableAddress[n] : +# 967| r967_3(int) = Load : &:r967_2, ~mu959_4 +# 967| r967_4(unsigned long) = Convert : r967_3 +# 967| r967_5(unsigned long) = Constant[4] : +# 967| r967_6(unsigned long) = Mul : r967_4, r967_5 +# 967| r967_7(void *) = Call : func:r967_1, 0:r967_6 +# 967| mu967_8(unknown) = ^CallSideEffect : ~mu959_4 +# 967| mu967_9(unknown) = ^InitializeDynamicAllocation : &:r967_7 +# 967| r967_10(int *) = Convert : r967_7 +# 968| v968_1(void) = NoOp : +# 959| v959_7(void) = ReturnVoid : +# 959| v959_8(void) = UnmodeledUse : mu* +# 959| v959_9(void) = AliasedUse : ~mu959_4 +# 959| v959_10(void) = ExitFunction : # 970| int designatedInit() # 970| Block 0 @@ -5012,7 +5622,7 @@ ir.cpp: # 996| mu996_4(unknown) = UnmodeledDefinition : # 996| r996_5(glval) = VariableAddress[a] : # 996| mu996_6(int *) = InitializeParameter[a] : &:r996_5 -# 996| r996_7(int *) = Load : &:r996_5, ~mu996_6 +# 996| r996_7(int *) = Load : &:r996_5, ~mu996_4 # 996| mu996_8(unknown) = InitializeIndirection[a] : &:r996_7 # 996| r996_9(glval<..(*)(..)>) = VariableAddress[fn] : # 996| mu996_10(..(*)(..)) = InitializeParameter[fn] : &:r996_9 @@ -5029,7 +5639,7 @@ ir.cpp: # 997| mu997_11(unknown) = ^CallSideEffect : ~mu996_4 # 997| r997_12(int) = Add : r997_6, r997_10 # 997| mu997_13(int) = Store : &:r997_1, r997_12 -# 996| v996_11(void) = ReturnIndirection : &:r996_7, ~mu996_4 +# 996| v996_11(void) = ReturnIndirection[a] : &:r996_7, ~mu996_4 # 996| r996_12(glval) = VariableAddress[#return] : # 996| v996_13(void) = ReturnValue : &:r996_12, ~mu996_4 # 996| v996_14(void) = UnmodeledUse : mu* @@ -5186,7 +5796,7 @@ ir.cpp: # 1040| mu1040_6(int) = InitializeParameter[x] : &:r1040_5 # 1040| r1040_7(glval) = VariableAddress[s] : # 1040| mu1040_8(String &) = InitializeParameter[s] : &:r1040_7 -# 1040| r1040_9(String &) = Load : &:r1040_7, ~mu1040_8 +# 1040| r1040_9(String &) = Load : &:r1040_7, ~mu1040_4 # 1040| mu1040_10(unknown) = InitializeIndirection[s] : &:r1040_9 # 1041| r1041_1(glval) = VariableAddress[lambda_empty] : # 1041| r1041_2(glval) = VariableAddress[#temp1041:23] : @@ -5339,7 +5949,7 @@ ir.cpp: # 1055| v1055_7(void) = ^BufferReadSideEffect[-1] : &:r1055_2, ~mu1040_4 # 1055| mu1055_8(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r1055_2 # 1056| v1056_1(void) = NoOp : -# 1040| v1040_11(void) = ReturnIndirection : &:r1040_9, ~mu1040_4 +# 1040| v1040_11(void) = ReturnIndirection[s] : &:r1040_9, ~mu1040_4 # 1040| v1040_12(void) = ReturnVoid : # 1040| v1040_13(void) = UnmodeledUse : mu* # 1040| v1040_14(void) = AliasedUse : ~mu1040_4 @@ -5609,7 +6219,7 @@ ir.cpp: # 1077| mu1077_4(unknown) = UnmodeledDefinition : # 1077| r1077_5(glval &>) = VariableAddress[v] : # 1077| mu1077_6(vector &) = InitializeParameter[v] : &:r1077_5 -# 1077| r1077_7(vector &) = Load : &:r1077_5, ~mu1077_6 +# 1077| r1077_7(vector &) = Load : &:r1077_5, ~mu1077_4 # 1077| mu1077_8(unknown) = InitializeIndirection[v] : &:r1077_7 # 1078| r1078_1(glval &>) = VariableAddress[(__range)] : # 1078| r1078_2(glval &>) = VariableAddress[v] : @@ -5690,13 +6300,13 @@ ir.cpp: #-----| Goto -> Block 5 # 1088| Block 5 -# 1088| v1088_1(void) = NoOp : -# 1089| v1089_1(void) = NoOp : -# 1077| v1077_9(void) = ReturnIndirection : &:r1077_7, ~mu1077_4 -# 1077| v1077_10(void) = ReturnVoid : -# 1077| v1077_11(void) = UnmodeledUse : mu* -# 1077| v1077_12(void) = AliasedUse : ~mu1077_4 -# 1077| v1077_13(void) = ExitFunction : +# 1088| v1088_1(void) = NoOp : +# 1089| v1089_1(void) = NoOp : +# 1077| v1077_9(void) = ReturnIndirection[v] : &:r1077_7, ~mu1077_4 +# 1077| v1077_10(void) = ReturnVoid : +# 1077| v1077_11(void) = UnmodeledUse : mu* +# 1077| v1077_12(void) = AliasedUse : ~mu1077_4 +# 1077| v1077_13(void) = ExitFunction : #-----| Block 6 #-----| r0_24(glval) = VariableAddress[(__begin)] : @@ -5802,13 +6412,13 @@ ir.cpp: # 1113| mu1113_4(unknown) = UnmodeledDefinition : # 1113| r1113_5(glval) = VariableAddress[a] : # 1113| mu1113_6(unsigned int &) = InitializeParameter[a] : &:r1113_5 -# 1113| r1113_7(unsigned int &) = Load : &:r1113_5, ~mu1113_6 +# 1113| r1113_7(unsigned int &) = Load : &:r1113_5, ~mu1113_4 # 1113| mu1113_8(unknown) = InitializeIndirection[a] : &:r1113_7 # 1113| r1113_9(glval) = VariableAddress[b] : # 1113| mu1113_10(unsigned int) = InitializeParameter[b] : &:r1113_9 # 1113| r1113_11(glval) = VariableAddress[c] : # 1113| mu1113_12(unsigned int &) = InitializeParameter[c] : &:r1113_11 -# 1113| r1113_13(unsigned int &) = Load : &:r1113_11, ~mu1113_12 +# 1113| r1113_13(unsigned int &) = Load : &:r1113_11, ~mu1113_4 # 1113| mu1113_14(unknown) = InitializeIndirection[c] : &:r1113_13 # 1113| r1113_15(glval) = VariableAddress[d] : # 1113| mu1113_16(unsigned int) = InitializeParameter[d] : &:r1113_15 @@ -5823,8 +6433,8 @@ ir.cpp: # 1118| r1118_9(unsigned int) = Load : &:r1118_8, ~mu1113_4 # 1115| mu1115_1(unknown) = InlineAsm : ~mu1113_4, 0:r1118_3, 1:r1118_4, 2:r1118_7, 3:r1118_9 # 1120| v1120_1(void) = NoOp : -# 1113| v1113_17(void) = ReturnIndirection : &:r1113_7, ~mu1113_4 -# 1113| v1113_18(void) = ReturnIndirection : &:r1113_13, ~mu1113_4 +# 1113| v1113_17(void) = ReturnIndirection[a] : &:r1113_7, ~mu1113_4 +# 1113| v1113_18(void) = ReturnIndirection[c] : &:r1113_13, ~mu1113_4 # 1113| v1113_19(void) = ReturnVoid : # 1113| v1113_20(void) = UnmodeledUse : mu* # 1113| v1113_21(void) = AliasedUse : ~mu1113_4 @@ -5972,7 +6582,7 @@ ir.cpp: # 1153| Block 10 # 1153| r1153_2(glval) = VariableAddress[s] : # 1153| mu1153_3(char *) = InitializeParameter[s] : &:r1153_2 -# 1153| r1153_4(char *) = Load : &:r1153_2, ~mu1153_3 +# 1153| r1153_4(char *) = Load : &:r1153_2, ~mu1142_4 # 1153| mu1153_5(unknown) = InitializeIndirection[s] : &:r1153_4 # 1154| r1154_1(glval) = VariableAddress[#throw1154:5] : # 1154| mu1154_2(String) = Uninitialized[#throw1154:5] : &:r1154_1 @@ -5995,7 +6605,7 @@ ir.cpp: # 1156| Block 12 # 1156| r1156_2(glval) = VariableAddress[e] : # 1156| mu1156_3(String &) = InitializeParameter[e] : &:r1156_2 -# 1156| r1156_4(String &) = Load : &:r1156_2, ~mu1156_3 +# 1156| r1156_4(String &) = Load : &:r1156_2, ~mu1142_4 # 1156| mu1156_5(unknown) = InitializeIndirection[e] : &:r1156_4 # 1156| v1156_6(void) = NoOp : #-----| Goto -> Block 13 @@ -6349,7 +6959,7 @@ ir.cpp: # 1240| mu1240_4(unknown) = UnmodeledDefinition : # 1240| r1240_5(glval) = VariableAddress[dynamic] : # 1240| mu1240_6(char *) = InitializeParameter[dynamic] : &:r1240_5 -# 1240| r1240_7(char *) = Load : &:r1240_5, ~mu1240_6 +# 1240| r1240_7(char *) = Load : &:r1240_5, ~mu1240_4 # 1240| mu1240_8(unknown) = InitializeIndirection[dynamic] : &:r1240_7 # 1241| r1241_1(glval) = VariableAddress[a#init] : # 1241| r1241_2(bool) = Load : &:r1241_1, ~mu1240_4 @@ -6400,12 +7010,12 @@ ir.cpp: #-----| Goto -> Block 5 # 1244| Block 5 -# 1244| v1244_1(void) = NoOp : -# 1240| v1240_9(void) = ReturnIndirection : &:r1240_7, ~mu1240_4 -# 1240| v1240_10(void) = ReturnVoid : -# 1240| v1240_11(void) = UnmodeledUse : mu* -# 1240| v1240_12(void) = AliasedUse : ~mu1240_4 -# 1240| v1240_13(void) = ExitFunction : +# 1244| v1244_1(void) = NoOp : +# 1240| v1240_9(void) = ReturnIndirection[dynamic] : &:r1240_7, ~mu1240_4 +# 1240| v1240_10(void) = ReturnVoid : +# 1240| v1240_11(void) = UnmodeledUse : mu* +# 1240| v1240_12(void) = AliasedUse : ~mu1240_4 +# 1240| v1240_13(void) = ExitFunction : # 1241| Block 6 # 1241| r1241_4(glval) = VariableAddress[a] : @@ -6417,6 +7027,237 @@ ir.cpp: # 1241| mu1241_6(bool) = Store : &:r1241_1, r1241_5 #-----| Goto -> Block 1 +# 1251| void test_strings(char*, char*) +# 1251| Block 0 +# 1251| v1251_1(void) = EnterFunction : +# 1251| mu1251_2(unknown) = AliasedDefinition : +# 1251| mu1251_3(unknown) = InitializeNonLocal : +# 1251| mu1251_4(unknown) = UnmodeledDefinition : +# 1251| r1251_5(glval) = VariableAddress[s1] : +# 1251| mu1251_6(char *) = InitializeParameter[s1] : &:r1251_5 +# 1251| r1251_7(char *) = Load : &:r1251_5, ~mu1251_4 +# 1251| mu1251_8(unknown) = InitializeIndirection[s1] : &:r1251_7 +# 1251| r1251_9(glval) = VariableAddress[s2] : +# 1251| mu1251_10(char *) = InitializeParameter[s2] : &:r1251_9 +# 1251| r1251_11(char *) = Load : &:r1251_9, ~mu1251_4 +# 1251| mu1251_12(unknown) = InitializeIndirection[s2] : &:r1251_11 +# 1252| r1252_1(glval) = VariableAddress[buffer] : +# 1252| mu1252_2(char[1024]) = Uninitialized[buffer] : &:r1252_1 +# 1252| r1252_3(int) = Constant[0] : +# 1252| r1252_4(glval) = PointerAdd[1] : r1252_1, r1252_3 +# 1252| r1252_5(char) = Constant[0] : +# 1252| mu1252_6(char) = Store : &:r1252_4, r1252_5 +# 1252| r1252_7(int) = Constant[1] : +# 1252| r1252_8(glval) = PointerAdd[1] : r1252_1, r1252_7 +# 1252| r1252_9(unknown[1023]) = Constant[0] : +# 1252| mu1252_10(unknown[1023]) = Store : &:r1252_8, r1252_9 +# 1254| r1254_1(glval) = FunctionAddress[strcpy] : +# 1254| r1254_2(glval) = VariableAddress[buffer] : +# 1254| r1254_3(char *) = Convert : r1254_2 +# 1254| r1254_4(glval) = VariableAddress[s1] : +# 1254| r1254_5(char *) = Load : &:r1254_4, ~mu1251_4 +# 1254| r1254_6(char *) = Convert : r1254_5 +# 1254| r1254_7(char *) = Call : func:r1254_1, 0:r1254_3, 1:r1254_6 +# 1254| v1254_8(void) = ^BufferReadSideEffect[1] : &:r1254_6, ~mu1251_4 +# 1254| mu1254_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1254_3 +# 1255| r1255_1(glval) = FunctionAddress[strcat] : +# 1255| r1255_2(glval) = VariableAddress[buffer] : +# 1255| r1255_3(char *) = Convert : r1255_2 +# 1255| r1255_4(glval) = VariableAddress[s2] : +# 1255| r1255_5(char *) = Load : &:r1255_4, ~mu1251_4 +# 1255| r1255_6(char *) = Convert : r1255_5 +# 1255| r1255_7(char *) = Call : func:r1255_1, 0:r1255_3, 1:r1255_6 +# 1255| v1255_8(void) = ^BufferReadSideEffect[0] : &:r1255_3, ~mu1251_4 +# 1255| v1255_9(void) = ^BufferReadSideEffect[1] : &:r1255_6, ~mu1251_4 +# 1255| mu1255_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1255_3 +# 1256| v1256_1(void) = NoOp : +# 1251| v1251_13(void) = ReturnIndirection[s1] : &:r1251_7, ~mu1251_4 +# 1251| v1251_14(void) = ReturnIndirection[s2] : &:r1251_11, ~mu1251_4 +# 1251| v1251_15(void) = ReturnVoid : +# 1251| v1251_16(void) = UnmodeledUse : mu* +# 1251| v1251_17(void) = AliasedUse : ~mu1251_4 +# 1251| v1251_18(void) = ExitFunction : + +# 1261| void A::static_member(A*, int) +# 1261| Block 0 +# 1261| v1261_1(void) = EnterFunction : +# 1261| mu1261_2(unknown) = AliasedDefinition : +# 1261| mu1261_3(unknown) = InitializeNonLocal : +# 1261| mu1261_4(unknown) = UnmodeledDefinition : +# 1261| r1261_5(glval) = VariableAddress[a] : +# 1261| mu1261_6(A *) = InitializeParameter[a] : &:r1261_5 +# 1261| r1261_7(A *) = Load : &:r1261_5, ~mu1261_4 +# 1261| mu1261_8(unknown) = InitializeIndirection[a] : &:r1261_7 +# 1261| r1261_9(glval) = VariableAddress[x] : +# 1261| mu1261_10(int) = InitializeParameter[x] : &:r1261_9 +# 1262| r1262_1(glval) = VariableAddress[x] : +# 1262| r1262_2(int) = Load : &:r1262_1, ~mu1261_4 +# 1262| r1262_3(glval) = VariableAddress[a] : +# 1262| r1262_4(A *) = Load : &:r1262_3, ~mu1261_4 +# 1262| r1262_5(glval) = FieldAddress[member] : r1262_4 +# 1262| mu1262_6(int) = Store : &:r1262_5, r1262_2 +# 1263| v1263_1(void) = NoOp : +# 1261| v1261_11(void) = ReturnIndirection[a] : &:r1261_7, ~mu1261_4 +# 1261| v1261_12(void) = ReturnVoid : +# 1261| v1261_13(void) = UnmodeledUse : mu* +# 1261| v1261_14(void) = AliasedUse : ~mu1261_4 +# 1261| v1261_15(void) = ExitFunction : + +# 1270| void test_static_member_functions(int, A*) +# 1270| Block 0 +# 1270| v1270_1(void) = EnterFunction : +# 1270| mu1270_2(unknown) = AliasedDefinition : +# 1270| mu1270_3(unknown) = InitializeNonLocal : +# 1270| mu1270_4(unknown) = UnmodeledDefinition : +# 1270| r1270_5(glval) = VariableAddress[int_arg] : +# 1270| mu1270_6(int) = InitializeParameter[int_arg] : &:r1270_5 +# 1270| r1270_7(glval) = VariableAddress[a_arg] : +# 1270| mu1270_8(A *) = InitializeParameter[a_arg] : &:r1270_7 +# 1270| r1270_9(A *) = Load : &:r1270_7, ~mu1270_4 +# 1270| mu1270_10(unknown) = InitializeIndirection[a_arg] : &:r1270_9 +# 1271| r1271_1(glval) = VariableAddress[c] : +# 1271| mu1271_2(C) = Uninitialized[c] : &:r1271_1 +# 1271| r1271_3(glval) = FunctionAddress[C] : +# 1271| v1271_4(void) = Call : func:r1271_3, this:r1271_1 +# 1271| mu1271_5(unknown) = ^CallSideEffect : ~mu1270_4 +# 1271| mu1271_6(C) = ^IndirectMayWriteSideEffect[-1] : &:r1271_1 +# 1272| r1272_1(glval) = VariableAddress[c] : +# 1272| r1272_2(glval) = FunctionAddress[StaticMemberFunction] : +# 1272| r1272_3(int) = Constant[10] : +# 1272| r1272_4(int) = Call : func:r1272_2, 0:r1272_3 +# 1272| mu1272_5(unknown) = ^CallSideEffect : ~mu1270_4 +# 1273| r1273_1(glval) = FunctionAddress[StaticMemberFunction] : +# 1273| r1273_2(int) = Constant[10] : +# 1273| r1273_3(int) = Call : func:r1273_1, 0:r1273_2 +# 1273| mu1273_4(unknown) = ^CallSideEffect : ~mu1270_4 +# 1275| r1275_1(glval) = VariableAddress[a] : +# 1275| mu1275_2(A) = Uninitialized[a] : &:r1275_1 +# 1276| r1276_1(glval) = VariableAddress[a] : +# 1276| r1276_2(glval) = FunctionAddress[static_member] : +# 1276| r1276_3(glval) = VariableAddress[a] : +# 1276| r1276_4(A *) = CopyValue : r1276_3 +# 1276| r1276_5(glval) = VariableAddress[int_arg] : +# 1276| r1276_6(int) = Load : &:r1276_5, ~mu1270_4 +# 1276| v1276_7(void) = Call : func:r1276_2, 0:r1276_4, 1:r1276_6 +# 1276| mu1276_8(unknown) = ^CallSideEffect : ~mu1270_4 +# 1276| v1276_9(void) = ^BufferReadSideEffect[0] : &:r1276_4, ~mu1270_4 +# 1276| mu1276_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1276_4 +# 1277| r1277_1(glval) = FunctionAddress[static_member] : +# 1277| r1277_2(glval) = VariableAddress[a] : +# 1277| r1277_3(A *) = CopyValue : r1277_2 +# 1277| r1277_4(glval) = VariableAddress[int_arg] : +# 1277| r1277_5(int) = Load : &:r1277_4, ~mu1270_4 +# 1277| v1277_6(void) = Call : func:r1277_1, 0:r1277_3, 1:r1277_5 +# 1277| mu1277_7(unknown) = ^CallSideEffect : ~mu1270_4 +# 1277| v1277_8(void) = ^BufferReadSideEffect[0] : &:r1277_3, ~mu1270_4 +# 1277| mu1277_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1277_3 +# 1279| r1279_1(glval) = VariableAddress[a] : +# 1279| r1279_2(A *) = CopyValue : r1279_1 +# 1279| r1279_3(glval) = FunctionAddress[static_member] : +# 1279| r1279_4(glval) = VariableAddress[a_arg] : +# 1279| r1279_5(A *) = Load : &:r1279_4, ~mu1270_4 +# 1279| r1279_6(glval) = VariableAddress[int_arg] : +# 1279| r1279_7(int) = Load : &:r1279_6, ~mu1270_4 +# 1279| r1279_8(int) = Constant[2] : +# 1279| r1279_9(int) = Add : r1279_7, r1279_8 +# 1279| v1279_10(void) = Call : func:r1279_3, 0:r1279_5, 1:r1279_9 +# 1279| mu1279_11(unknown) = ^CallSideEffect : ~mu1270_4 +# 1279| v1279_12(void) = ^BufferReadSideEffect[0] : &:r1279_5, ~mu1270_4 +# 1279| mu1279_13(unknown) = ^BufferMayWriteSideEffect[0] : &:r1279_5 +# 1280| r1280_1(glval) = VariableAddress[a_arg] : +# 1280| r1280_2(A *) = Load : &:r1280_1, ~mu1270_4 +# 1280| r1280_3(glval) = CopyValue : r1280_2 +# 1280| r1280_4(glval) = FunctionAddress[static_member] : +# 1280| r1280_5(glval) = VariableAddress[a] : +# 1280| r1280_6(A *) = CopyValue : r1280_5 +# 1280| r1280_7(int) = Constant[99] : +# 1280| v1280_8(void) = Call : func:r1280_4, 0:r1280_6, 1:r1280_7 +# 1280| mu1280_9(unknown) = ^CallSideEffect : ~mu1270_4 +# 1280| v1280_10(void) = ^BufferReadSideEffect[0] : &:r1280_6, ~mu1270_4 +# 1280| mu1280_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r1280_6 +# 1281| r1281_1(glval) = VariableAddress[a_arg] : +# 1281| r1281_2(A *) = Load : &:r1281_1, ~mu1270_4 +# 1281| r1281_3(glval) = FunctionAddress[static_member] : +# 1281| r1281_4(glval) = VariableAddress[a_arg] : +# 1281| r1281_5(A *) = Load : &:r1281_4, ~mu1270_4 +# 1281| r1281_6(int) = Constant[-1] : +# 1281| v1281_7(void) = Call : func:r1281_3, 0:r1281_5, 1:r1281_6 +# 1281| mu1281_8(unknown) = ^CallSideEffect : ~mu1270_4 +# 1281| v1281_9(void) = ^BufferReadSideEffect[0] : &:r1281_5, ~mu1270_4 +# 1281| mu1281_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1281_5 +# 1283| r1283_1(glval) = VariableAddress[a] : +# 1283| r1283_2(glval) = FunctionAddress[static_member_without_def] : +# 1283| v1283_3(void) = Call : func:r1283_2 +# 1283| mu1283_4(unknown) = ^CallSideEffect : ~mu1270_4 +# 1284| r1284_1(glval) = FunctionAddress[static_member_without_def] : +# 1284| v1284_2(void) = Call : func:r1284_1 +# 1284| mu1284_3(unknown) = ^CallSideEffect : ~mu1270_4 +# 1286| r1286_1(glval) = FunctionAddress[getAnInstanceOfA] : +# 1286| r1286_2(A *) = Call : func:r1286_1 +# 1286| mu1286_3(unknown) = ^CallSideEffect : ~mu1270_4 +# 1286| r1286_4(glval) = FunctionAddress[static_member_without_def] : +# 1286| v1286_5(void) = Call : func:r1286_4 +# 1286| mu1286_6(unknown) = ^CallSideEffect : ~mu1270_4 +# 1287| v1287_1(void) = NoOp : +# 1270| v1270_11(void) = ReturnIndirection[a_arg] : &:r1270_9, ~mu1270_4 +# 1270| v1270_12(void) = ReturnVoid : +# 1270| v1270_13(void) = UnmodeledUse : mu* +# 1270| v1270_14(void) = AliasedUse : ~mu1270_4 +# 1270| v1270_15(void) = ExitFunction : + +# 1289| int missingReturnValue(bool, int) +# 1289| Block 0 +# 1289| v1289_1(void) = EnterFunction : +# 1289| mu1289_2(unknown) = AliasedDefinition : +# 1289| mu1289_3(unknown) = InitializeNonLocal : +# 1289| mu1289_4(unknown) = UnmodeledDefinition : +# 1289| r1289_5(glval) = VariableAddress[b] : +# 1289| mu1289_6(bool) = InitializeParameter[b] : &:r1289_5 +# 1289| r1289_7(glval) = VariableAddress[x] : +# 1289| mu1289_8(int) = InitializeParameter[x] : &:r1289_7 +# 1290| r1290_1(glval) = VariableAddress[b] : +# 1290| r1290_2(bool) = Load : &:r1290_1, ~mu1289_4 +# 1290| v1290_3(void) = ConditionalBranch : r1290_2 +#-----| False -> Block 1 +#-----| True -> Block 2 + +# 1293| Block 1 +# 1293| v1293_1(void) = Unreached : + +# 1291| Block 2 +# 1291| r1291_1(glval) = VariableAddress[#return] : +# 1291| r1291_2(glval) = VariableAddress[x] : +# 1291| r1291_3(int) = Load : &:r1291_2, ~mu1289_4 +# 1291| mu1291_4(int) = Store : &:r1291_1, r1291_3 +# 1289| r1289_9(glval) = VariableAddress[#return] : +# 1289| v1289_10(void) = ReturnValue : &:r1289_9, ~mu1289_4 +# 1289| v1289_11(void) = UnmodeledUse : mu* +# 1289| v1289_12(void) = AliasedUse : ~mu1289_4 +# 1289| v1289_13(void) = ExitFunction : + +# 1295| void returnVoid(int, int) +# 1295| Block 0 +# 1295| v1295_1(void) = EnterFunction : +# 1295| mu1295_2(unknown) = AliasedDefinition : +# 1295| mu1295_3(unknown) = InitializeNonLocal : +# 1295| mu1295_4(unknown) = UnmodeledDefinition : +# 1295| r1295_5(glval) = VariableAddress[x] : +# 1295| mu1295_6(int) = InitializeParameter[x] : &:r1295_5 +# 1295| r1295_7(glval) = VariableAddress[y] : +# 1295| mu1295_8(int) = InitializeParameter[y] : &:r1295_7 +# 1296| r1296_1(glval) = FunctionAddress[IntegerOps] : +# 1296| r1296_2(glval) = VariableAddress[x] : +# 1296| r1296_3(int) = Load : &:r1296_2, ~mu1295_4 +# 1296| r1296_4(glval) = VariableAddress[y] : +# 1296| r1296_5(int) = Load : &:r1296_4, ~mu1295_4 +# 1296| v1296_6(void) = Call : func:r1296_1, 0:r1296_3, 1:r1296_5 +# 1296| mu1296_7(unknown) = ^CallSideEffect : ~mu1295_4 +# 1296| v1296_8(void) = NoOp : +# 1295| v1295_9(void) = ReturnVoid : +# 1295| v1295_10(void) = UnmodeledUse : mu* +# 1295| v1295_11(void) = AliasedUse : ~mu1295_4 +# 1295| v1295_12(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 @@ -6447,12 +7288,13 @@ perf-regression.cpp: # 10| r10_3(unsigned long) = Constant[1073741824] : # 10| r10_4(void *) = Call : func:r10_2, 0:r10_3 # 10| mu10_5(unknown) = ^CallSideEffect : ~mu9_4 -# 10| r10_6(Big *) = Convert : r10_4 -# 10| r10_7(glval) = FunctionAddress[Big] : -# 10| v10_8(void) = Call : func:r10_7, this:r10_6 -# 10| mu10_9(unknown) = ^CallSideEffect : ~mu9_4 -# 10| mu10_10(Big) = ^IndirectMayWriteSideEffect[-1] : &:r10_6 -# 10| mu10_11(Big *) = Store : &:r10_1, r10_6 +# 10| mu10_6(unknown) = ^InitializeDynamicAllocation : &:r10_4 +# 10| r10_7(Big *) = Convert : r10_4 +# 10| r10_8(glval) = FunctionAddress[Big] : +# 10| v10_9(void) = Call : func:r10_8, this:r10_7 +# 10| mu10_10(unknown) = ^CallSideEffect : ~mu9_4 +# 10| mu10_11(Big) = ^IndirectMayWriteSideEffect[-1] : &:r10_7 +# 10| mu10_12(Big *) = Store : &:r10_1, r10_7 # 12| r12_1(glval) = VariableAddress[#return] : # 12| r12_2(int) = Constant[0] : # 12| mu12_3(int) = Store : &:r12_1, r12_2 @@ -6471,14 +7313,14 @@ struct_init.cpp: # 16| mu16_4(unknown) = UnmodeledDefinition : # 16| r16_5(glval) = VariableAddress[info] : # 16| mu16_6(Info *) = InitializeParameter[info] : &:r16_5 -# 16| r16_7(Info *) = Load : &:r16_5, ~mu16_6 +# 16| r16_7(Info *) = Load : &:r16_5, ~mu16_4 # 16| mu16_8(unknown) = InitializeIndirection[info] : &:r16_7 # 17| r17_1(glval) = VariableAddress[info] : # 17| r17_2(Info *) = Load : &:r17_1, ~mu16_4 # 17| r17_3(glval) = VariableAddress[global_pointer] : # 17| mu17_4(Info *) = Store : &:r17_3, r17_2 # 18| v18_1(void) = NoOp : -# 16| v16_9(void) = ReturnIndirection : &:r16_7, ~mu16_4 +# 16| v16_9(void) = ReturnIndirection[info] : &:r16_7, ~mu16_4 # 16| v16_10(void) = ReturnVoid : # 16| v16_11(void) = UnmodeledUse : mu* # 16| v16_12(void) = AliasedUse : ~mu16_4 @@ -6551,7 +7393,7 @@ struct_init.cpp: # 36| mu36_4(unknown) = UnmodeledDefinition : # 36| r36_5(glval) = VariableAddress[name1] : # 36| mu36_6(char *) = InitializeParameter[name1] : &:r36_5 -# 36| r36_7(char *) = Load : &:r36_5, ~mu36_6 +# 36| r36_7(char *) = Load : &:r36_5, ~mu36_4 # 36| mu36_8(unknown) = InitializeIndirection[name1] : &:r36_7 # 37| r37_1(glval) = VariableAddress[static_infos#init] : # 37| r37_2(bool) = Load : &:r37_1, ~mu36_4 @@ -6568,7 +7410,7 @@ struct_init.cpp: # 41| v41_6(void) = ^BufferReadSideEffect[0] : &:r41_3, ~mu36_4 # 41| mu41_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r41_3 # 42| v42_1(void) = NoOp : -# 36| v36_9(void) = ReturnIndirection : &:r36_7, ~mu36_4 +# 36| v36_9(void) = ReturnIndirection[name1] : &:r36_7, ~mu36_4 # 36| v36_10(void) = ReturnVoid : # 36| v36_11(void) = UnmodeledUse : mu* # 36| v36_12(void) = AliasedUse : ~mu36_4 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected index 735555b5a4b..3a1a30265b2 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity_unsound.expected @@ -13,6 +13,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index e271e7bfff3..8fdffc0569a 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -89,7 +89,7 @@ ssa.cpp: # 28| r28_12(int) = Load : &:r28_11, m28_1 # 28| r28_13(int) = Add : r28_8, r28_12 # 28| m28_14(int) = Store : &:r28_4, r28_13 -# 13| v13_14(void) = ReturnIndirection : &:r13_8, m28_3 +# 13| v13_14(void) = ReturnIndirection[p] : &:r13_8, m28_3 # 13| r13_15(glval) = VariableAddress[#return] : # 13| v13_16(void) = ReturnValue : &:r13_15, m28_14 # 13| v13_17(void) = UnmodeledUse : mu* @@ -257,12 +257,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_12(void) = ReturnIndirection : &:r68_10, m68_11 -# 68| v68_13(void) = ReturnVoid : -# 68| v68_14(void) = UnmodeledUse : mu* -# 68| v68_15(void) = AliasedUse : ~m69_3 -# 68| v68_16(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_12(void) = ReturnIndirection[p] : &:r68_10, m68_11 +# 68| v68_13(void) = ReturnVoid : +# 68| v68_14(void) = UnmodeledUse : mu* +# 68| v68_15(void) = AliasedUse : ~m69_3 +# 68| v68_16(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -806,7 +806,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_7 # 181| r181_4(int) = Load : &:r181_3, ~m179_9 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_10(void) = ReturnIndirection : &:r179_8, m179_9 +# 179| v179_10(void) = ReturnIndirection[p] : &:r179_8, m179_9 # 179| r179_11(glval) = VariableAddress[#return] : # 179| v179_12(void) = ReturnValue : &:r179_11, m181_5 # 179| v179_13(void) = UnmodeledUse : mu* @@ -853,10 +853,10 @@ ssa.cpp: # 186| m186_1(unknown) = InlineAsm : ~m184_15, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 186| m186_2(unknown) = Chi : total:m184_15, partial:m186_1 # 192| v192_1(void) = NoOp : -# 184| v184_24(void) = ReturnIndirection : &:r184_8, ~m186_2 -# 184| v184_25(void) = ReturnIndirection : &:r184_13, ~m186_2 -# 184| v184_26(void) = ReturnIndirection : &:r184_18, m184_19 -# 184| v184_27(void) = ReturnIndirection : &:r184_22, m184_23 +# 184| v184_24(void) = ReturnIndirection[a] : &:r184_8, ~m186_2 +# 184| v184_25(void) = ReturnIndirection[b] : &:r184_13, ~m186_2 +# 184| v184_26(void) = ReturnIndirection[c] : &:r184_18, m184_19 +# 184| v184_27(void) = ReturnIndirection[d] : &:r184_22, m184_23 # 184| v184_28(void) = ReturnVoid : # 184| v184_29(void) = UnmodeledUse : mu* # 184| v184_30(void) = AliasedUse : ~m186_2 @@ -913,8 +913,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_16(void) = ReturnIndirection : &:r198_8, m198_9 -# 198| v198_17(void) = ReturnIndirection : &:r198_12, m198_13 +# 198| v198_16(void) = ReturnIndirection[str1] : &:r198_8, m198_9 +# 198| v198_17(void) = ReturnIndirection[str2] : &:r198_12, m198_13 # 198| r198_18(glval) = VariableAddress[#return] : # 198| v198_19(void) = ReturnValue : &:r198_18, m202_4 # 198| v198_20(void) = UnmodeledUse : mu* @@ -1162,17 +1162,19 @@ ssa.cpp: # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| m248_9(unknown) = ^CallSideEffect : ~m247_10 # 248| m248_10(unknown) = Chi : total:m247_10, partial:m248_9 -# 248| r248_11(char *) = Convert : r248_8 -# 248| m248_12(char *) = Store : &:r248_1, r248_11 +# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| m248_12(unknown) = Chi : total:m248_10, partial:m248_11 +# 248| r248_13(char *) = Convert : r248_8 +# 248| m248_14(char *) = Store : &:r248_1, r248_13 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_7 # 249| r249_4(glval) = CopyValue : r249_3 # 249| m249_5(char) = Store : &:r249_4, r249_1 -# 249| m249_6(unknown) = Chi : total:m248_10, partial:m249_5 +# 249| m249_6(unknown) = Chi : total:m248_12, partial:m249_5 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_12 +# 250| r250_3(char *) = Load : &:r250_2, m248_14 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_7 @@ -1185,9 +1187,9 @@ ssa.cpp: # 250| m250_13(unknown) = Chi : total:m249_6, partial:m250_12 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_12 +# 251| r251_3(char *) = Load : &:r251_2, m248_14 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_13(void) = ReturnIndirection : &:r247_8, ~m250_13 +# 247| v247_13(void) = ReturnIndirection[src] : &:r247_8, ~m250_13 # 247| r247_14(glval) = VariableAddress[#return] : # 247| v247_15(void) = ReturnValue : &:r247_14, m251_4 # 247| v247_16(void) = UnmodeledUse : mu* @@ -1281,7 +1283,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_10 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_13(void) = ReturnIndirection : &:r268_8, ~m270_11 +# 268| v268_13(void) = ReturnIndirection[s] : &:r268_8, ~m270_11 # 268| r268_14(glval) = VariableAddress[#return] : # 268| v268_15(void) = ReturnValue : &:r268_14, m271_4 # 268| v268_16(void) = UnmodeledUse : mu* @@ -1345,3 +1347,189 @@ ssa.cpp: # 275| v275_13(void) = UnmodeledUse : mu* # 275| v275_14(void) = AliasedUse : ~m281_2 # 275| v275_15(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| m286_2(unknown) = AliasedDefinition : +# 286| m286_3(unknown) = InitializeNonLocal : +# 286| m286_4(unknown) = Chi : total:m286_2, partial:m286_3 +# 286| mu286_5(unknown) = UnmodeledDefinition : +# 286| r286_6(glval) = InitializeThis : +# 286| r286_7(glval) = VariableAddress[x] : +# 286| m286_8(int) = InitializeParameter[x] : &:r286_7 +# 286| v286_9(void) = NoOp : +# 286| v286_10(void) = ReturnVoid : +# 286| v286_11(void) = UnmodeledUse : mu* +# 286| v286_12(void) = AliasedUse : m286_3 +# 286| v286_13(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| m287_2(unknown) = AliasedDefinition : +# 287| m287_3(unknown) = InitializeNonLocal : +# 287| m287_4(unknown) = Chi : total:m287_2, partial:m287_3 +# 287| mu287_5(unknown) = UnmodeledDefinition : +# 287| r287_6(glval) = InitializeThis : +# 287| r287_7(glval) = VariableAddress[p#0] : +# 287| m287_8(A *) = InitializeParameter[p#0] : &:r287_7 +# 287| r287_9(A *) = Load : &:r287_7, m287_8 +# 287| m287_10(unknown) = InitializeIndirection[p#0] : &:r287_9 +# 287| v287_11(void) = NoOp : +# 287| v287_12(void) = ReturnIndirection[p#0] : &:r287_9, m287_10 +# 287| v287_13(void) = ReturnVoid : +# 287| v287_14(void) = UnmodeledUse : mu* +# 287| v287_15(void) = AliasedUse : m287_3 +# 287| v287_16(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| m288_2(unknown) = AliasedDefinition : +# 288| m288_3(unknown) = InitializeNonLocal : +# 288| m288_4(unknown) = Chi : total:m288_2, partial:m288_3 +# 288| mu288_5(unknown) = UnmodeledDefinition : +# 288| r288_6(glval) = InitializeThis : +# 288| v288_7(void) = NoOp : +# 288| v288_8(void) = ReturnVoid : +# 288| v288_9(void) = UnmodeledUse : mu* +# 288| v288_10(void) = AliasedUse : m288_3 +# 288| v288_11(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| m291_2(unknown) = AliasedDefinition : +# 291| m291_3(unknown) = InitializeNonLocal : +# 291| m291_4(unknown) = Chi : total:m291_2, partial:m291_3 +# 291| mu291_5(unknown) = UnmodeledDefinition : +# 291| r291_6(glval) = VariableAddress[x] : +# 291| m291_7(int) = InitializeParameter[x] : &:r291_6 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 +# 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 +# 292| m292_7(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_8(Point *) = Convert : r292_4 +# 292| m292_9(Point *) = Store : &:r292_1, r292_8 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 +# 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 +# 293| m293_7(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_8(Point *) = Convert : r293_4 +# 293| m293_9(Point *) = Store : &:r293_1, r293_8 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 +# 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 +# 294| m294_7(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_8(A *) = Convert : r294_4 +# 294| r294_9(glval) = FunctionAddress[A] : +# 294| r294_10(glval) = FunctionAddress[operator new] : +# 294| r294_11(unsigned long) = Constant[4] : +# 294| r294_12(void *) = Call : func:r294_10, 0:r294_11 +# 294| m294_13(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_14(unknown) = Chi : total:m294_6, partial:m294_13 +# 294| m294_15(unknown) = ^InitializeDynamicAllocation : &:r294_12 +# 294| r294_16(A *) = Convert : r294_12 +# 294| r294_17(glval) = FunctionAddress[A] : +# 294| r294_18(glval) = VariableAddress[x] : +# 294| r294_19(int) = Load : &:r294_18, m291_7 +# 294| v294_20(void) = Call : func:r294_17, this:r294_16, 0:r294_19 +# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 +# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 +# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 +# 294| v294_25(void) = Call : func:r294_9, this:r294_8, 0:r294_16 +# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 +# 294| m294_28(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_29(unknown) = Chi : total:m294_7, partial:m294_28 +# 294| v294_30(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 +# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 +# 294| r294_33(glval) = FieldAddress[i] : r294_8 +# 294| r294_34(int) = Load : &:r294_33, ~m294_29 +# 294| m294_35(int) = Store : &:r294_1, r294_34 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 +# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_8(A *) = Convert : r295_4 +# 295| r295_9(glval) = FunctionAddress[A] : +# 295| v295_10(void) = Call : func:r295_9, this:r295_8 +# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 +# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 +# 295| m295_15(A *) = Store : &:r295_1, r295_8 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_9 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_8(glval) = VariableAddress[#return] : +# 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 +# 291| v291_10(void) = UnmodeledUse : mu* +# 291| v291_11(void) = AliasedUse : ~m295_12 +# 291| v291_12(void) = ExitFunction : + +# 301| int main(int, char**) +# 301| Block 0 +# 301| v301_1(void) = EnterFunction : +# 301| m301_2(unknown) = AliasedDefinition : +# 301| m301_3(unknown) = InitializeNonLocal : +# 301| m301_4(unknown) = Chi : total:m301_2, partial:m301_3 +# 301| mu301_5(unknown) = UnmodeledDefinition : +# 301| r301_6(glval) = VariableAddress[argc] : +# 301| m301_7(int) = InitializeParameter[argc] : &:r301_6 +# 301| r301_8(glval) = VariableAddress[argv] : +# 301| m301_9(char **) = InitializeParameter[argv] : &:r301_8 +# 301| r301_10(char **) = Load : &:r301_8, m301_9 +# 301| m301_11(unknown) = InitializeIndirection[argv] : &:r301_10 +# 301| m301_12(unknown) = Chi : total:m301_4, partial:m301_11 +# 302| r302_1(glval) = FunctionAddress[unknownFunction] : +# 302| r302_2(glval) = VariableAddress[argc] : +# 302| r302_3(int) = Load : &:r302_2, m301_7 +# 302| r302_4(glval) = VariableAddress[argv] : +# 302| r302_5(char **) = Load : &:r302_4, m301_9 +# 302| v302_6(void) = Call : func:r302_1, 0:r302_3, 1:r302_5 +# 302| m302_7(unknown) = ^CallSideEffect : ~m301_12 +# 302| m302_8(unknown) = Chi : total:m301_12, partial:m302_7 +# 302| v302_9(void) = ^BufferReadSideEffect[1] : &:r302_5, ~m302_8 +# 302| m302_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r302_5 +# 302| m302_11(unknown) = Chi : total:m302_8, partial:m302_10 +# 303| r303_1(glval) = FunctionAddress[unknownFunction] : +# 303| r303_2(glval) = VariableAddress[argc] : +# 303| r303_3(int) = Load : &:r303_2, m301_7 +# 303| r303_4(glval) = VariableAddress[argv] : +# 303| r303_5(char **) = Load : &:r303_4, m301_9 +# 303| v303_6(void) = Call : func:r303_1, 0:r303_3, 1:r303_5 +# 303| m303_7(unknown) = ^CallSideEffect : ~m302_11 +# 303| m303_8(unknown) = Chi : total:m302_11, partial:m303_7 +# 303| v303_9(void) = ^BufferReadSideEffect[1] : &:r303_5, ~m303_8 +# 303| m303_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r303_5 +# 303| m303_11(unknown) = Chi : total:m303_8, partial:m303_10 +# 304| r304_1(glval) = VariableAddress[#return] : +# 304| r304_2(glval) = VariableAddress[argv] : +# 304| r304_3(char **) = Load : &:r304_2, m301_9 +# 304| r304_4(char *) = Load : &:r304_3, ~m303_11 +# 304| r304_5(char) = Load : &:r304_4, ~m303_11 +# 304| r304_6(int) = Convert : r304_5 +# 304| m304_7(int) = Store : &:r304_1, r304_6 +# 301| v301_13(void) = ReturnIndirection[argv] : &:r301_10, ~m303_11 +# 301| r301_14(glval) = VariableAddress[#return] : +# 301| v301_15(void) = ReturnValue : &:r301_14, m304_7 +# 301| v301_16(void) = UnmodeledUse : mu* +# 301| v301_17(void) = AliasedUse : ~m303_11 +# 301| v301_18(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected index 0566e36756b..01af278d8d9 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir_unsound.expected @@ -89,7 +89,7 @@ ssa.cpp: # 28| r28_12(int) = Load : &:r28_11, m28_1 # 28| r28_13(int) = Add : r28_8, r28_12 # 28| m28_14(int) = Store : &:r28_4, r28_13 -# 13| v13_14(void) = ReturnIndirection : &:r13_8, m28_3 +# 13| v13_14(void) = ReturnIndirection[p] : &:r13_8, m28_3 # 13| r13_15(glval) = VariableAddress[#return] : # 13| v13_16(void) = ReturnValue : &:r13_15, m28_14 # 13| v13_17(void) = UnmodeledUse : mu* @@ -257,12 +257,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_12(void) = ReturnIndirection : &:r68_10, m68_11 -# 68| v68_13(void) = ReturnVoid : -# 68| v68_14(void) = UnmodeledUse : mu* -# 68| v68_15(void) = AliasedUse : ~m69_3 -# 68| v68_16(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_12(void) = ReturnIndirection[p] : &:r68_10, m68_11 +# 68| v68_13(void) = ReturnVoid : +# 68| v68_14(void) = UnmodeledUse : mu* +# 68| v68_15(void) = AliasedUse : ~m69_3 +# 68| v68_16(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -803,7 +803,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_7 # 181| r181_4(int) = Load : &:r181_3, ~m179_9 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_10(void) = ReturnIndirection : &:r179_8, m179_9 +# 179| v179_10(void) = ReturnIndirection[p] : &:r179_8, m179_9 # 179| r179_11(glval) = VariableAddress[#return] : # 179| v179_12(void) = ReturnValue : &:r179_11, m181_5 # 179| v179_13(void) = UnmodeledUse : mu* @@ -848,10 +848,10 @@ ssa.cpp: # 186| m186_1(unknown) = InlineAsm : ~m184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 186| m186_2(unknown) = Chi : total:m184_4, partial:m186_1 # 192| v192_1(void) = NoOp : -# 184| v184_22(void) = ReturnIndirection : &:r184_8, m184_9 -# 184| v184_23(void) = ReturnIndirection : &:r184_12, m184_13 -# 184| v184_24(void) = ReturnIndirection : &:r184_16, m184_17 -# 184| v184_25(void) = ReturnIndirection : &:r184_20, m184_21 +# 184| v184_22(void) = ReturnIndirection[a] : &:r184_8, m184_9 +# 184| v184_23(void) = ReturnIndirection[b] : &:r184_12, m184_13 +# 184| v184_24(void) = ReturnIndirection[c] : &:r184_16, m184_17 +# 184| v184_25(void) = ReturnIndirection[d] : &:r184_20, m184_21 # 184| v184_26(void) = ReturnVoid : # 184| v184_27(void) = UnmodeledUse : mu* # 184| v184_28(void) = AliasedUse : ~m186_2 @@ -908,8 +908,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_16(void) = ReturnIndirection : &:r198_8, m198_9 -# 198| v198_17(void) = ReturnIndirection : &:r198_12, m198_13 +# 198| v198_16(void) = ReturnIndirection[str1] : &:r198_8, m198_9 +# 198| v198_17(void) = ReturnIndirection[str2] : &:r198_12, m198_13 # 198| r198_18(glval) = VariableAddress[#return] : # 198| v198_19(void) = ReturnValue : &:r198_18, m202_4 # 198| v198_20(void) = UnmodeledUse : mu* @@ -1154,8 +1154,9 @@ ssa.cpp: # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| m248_9(unknown) = ^CallSideEffect : ~m247_4 # 248| m248_10(unknown) = Chi : total:m247_4, partial:m248_9 -# 248| r248_11(char *) = Convert : r248_8 -# 248| m248_12(char *) = Store : &:r248_1, r248_11 +# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_12(char *) = Convert : r248_8 +# 248| m248_13(char *) = Store : &:r248_1, r248_12 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_7 @@ -1164,7 +1165,7 @@ ssa.cpp: # 249| m249_6(unknown) = Chi : total:m247_9, partial:m249_5 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_12 +# 250| r250_3(char *) = Load : &:r250_2, m248_13 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_7 @@ -1174,16 +1175,16 @@ ssa.cpp: # 250| r250_10(void *) = Call : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9 # 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6 # 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 -# 250| m250_13(unknown) = Chi : total:m248_10, partial:m250_12 +# 250| m250_13(unknown) = Chi : total:m248_11, partial:m250_12 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_12 +# 251| r251_3(char *) = Load : &:r251_2, m248_13 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_12(void) = ReturnIndirection : &:r247_8, m249_6 +# 247| v247_12(void) = ReturnIndirection[src] : &:r247_8, m249_6 # 247| r247_13(glval) = VariableAddress[#return] : # 247| v247_14(void) = ReturnValue : &:r247_13, m251_4 # 247| v247_15(void) = UnmodeledUse : mu* -# 247| v247_16(void) = AliasedUse : ~m250_13 +# 247| v247_16(void) = AliasedUse : ~m248_10 # 247| v247_17(void) = ExitFunction : # 254| char StringLiteralAliasing2(bool) @@ -1271,7 +1272,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_9 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_12(void) = ReturnIndirection : &:r268_8, m268_9 +# 268| v268_12(void) = ReturnIndirection[s] : &:r268_8, m268_9 # 268| r268_13(glval) = VariableAddress[#return] : # 268| v268_14(void) = ReturnValue : &:r268_13, m271_4 # 268| v268_15(void) = UnmodeledUse : mu* @@ -1334,3 +1335,188 @@ ssa.cpp: # 275| v275_13(void) = UnmodeledUse : mu* # 275| v275_14(void) = AliasedUse : ~m277_5 # 275| v275_15(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| m286_2(unknown) = AliasedDefinition : +# 286| m286_3(unknown) = InitializeNonLocal : +# 286| m286_4(unknown) = Chi : total:m286_2, partial:m286_3 +# 286| mu286_5(unknown) = UnmodeledDefinition : +# 286| r286_6(glval) = InitializeThis : +# 286| r286_7(glval) = VariableAddress[x] : +# 286| m286_8(int) = InitializeParameter[x] : &:r286_7 +# 286| v286_9(void) = NoOp : +# 286| v286_10(void) = ReturnVoid : +# 286| v286_11(void) = UnmodeledUse : mu* +# 286| v286_12(void) = AliasedUse : m286_3 +# 286| v286_13(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| m287_2(unknown) = AliasedDefinition : +# 287| m287_3(unknown) = InitializeNonLocal : +# 287| m287_4(unknown) = Chi : total:m287_2, partial:m287_3 +# 287| mu287_5(unknown) = UnmodeledDefinition : +# 287| r287_6(glval) = InitializeThis : +# 287| r287_7(glval) = VariableAddress[p#0] : +# 287| m287_8(A *) = InitializeParameter[p#0] : &:r287_7 +# 287| r287_9(A *) = Load : &:r287_7, m287_8 +# 287| m287_10(unknown) = InitializeIndirection[p#0] : &:r287_9 +# 287| v287_11(void) = NoOp : +# 287| v287_12(void) = ReturnIndirection[p#0] : &:r287_9, m287_10 +# 287| v287_13(void) = ReturnVoid : +# 287| v287_14(void) = UnmodeledUse : mu* +# 287| v287_15(void) = AliasedUse : m287_3 +# 287| v287_16(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| m288_2(unknown) = AliasedDefinition : +# 288| m288_3(unknown) = InitializeNonLocal : +# 288| m288_4(unknown) = Chi : total:m288_2, partial:m288_3 +# 288| mu288_5(unknown) = UnmodeledDefinition : +# 288| r288_6(glval) = InitializeThis : +# 288| v288_7(void) = NoOp : +# 288| v288_8(void) = ReturnVoid : +# 288| v288_9(void) = UnmodeledUse : mu* +# 288| v288_10(void) = AliasedUse : m288_3 +# 288| v288_11(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| m291_2(unknown) = AliasedDefinition : +# 291| m291_3(unknown) = InitializeNonLocal : +# 291| m291_4(unknown) = Chi : total:m291_2, partial:m291_3 +# 291| mu291_5(unknown) = UnmodeledDefinition : +# 291| r291_6(glval) = VariableAddress[x] : +# 291| m291_7(int) = InitializeParameter[x] : &:r291_6 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| m292_5(unknown) = ^CallSideEffect : ~m291_4 +# 292| m292_6(unknown) = Chi : total:m291_4, partial:m292_5 +# 292| m292_7(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_8(Point *) = Convert : r292_4 +# 292| m292_9(Point *) = Store : &:r292_1, r292_8 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| m293_5(unknown) = ^CallSideEffect : ~m292_6 +# 293| m293_6(unknown) = Chi : total:m292_6, partial:m293_5 +# 293| m293_7(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_8(Point *) = Convert : r293_4 +# 293| m293_9(Point *) = Store : &:r293_1, r293_8 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| m294_5(unknown) = ^CallSideEffect : ~m293_6 +# 294| m294_6(unknown) = Chi : total:m293_6, partial:m294_5 +# 294| m294_7(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_8(A *) = Convert : r294_4 +# 294| r294_9(glval) = FunctionAddress[A] : +# 294| r294_10(glval) = FunctionAddress[operator new] : +# 294| r294_11(unsigned long) = Constant[4] : +# 294| r294_12(void *) = Call : func:r294_10, 0:r294_11 +# 294| m294_13(unknown) = ^CallSideEffect : ~m294_6 +# 294| m294_14(unknown) = Chi : total:m294_6, partial:m294_13 +# 294| m294_15(unknown) = ^InitializeDynamicAllocation : &:r294_12 +# 294| r294_16(A *) = Convert : r294_12 +# 294| r294_17(glval) = FunctionAddress[A] : +# 294| r294_18(glval) = VariableAddress[x] : +# 294| r294_19(int) = Load : &:r294_18, m291_7 +# 294| v294_20(void) = Call : func:r294_17, this:r294_16, 0:r294_19 +# 294| m294_21(unknown) = ^CallSideEffect : ~m294_14 +# 294| m294_22(unknown) = Chi : total:m294_14, partial:m294_21 +# 294| m294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_16 +# 294| m294_24(unknown) = Chi : total:m294_15, partial:m294_23 +# 294| v294_25(void) = Call : func:r294_9, this:r294_8, 0:r294_16 +# 294| m294_26(unknown) = ^CallSideEffect : ~m294_22 +# 294| m294_27(unknown) = Chi : total:m294_22, partial:m294_26 +# 294| m294_28(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_8 +# 294| m294_29(unknown) = Chi : total:m294_7, partial:m294_28 +# 294| v294_30(void) = ^BufferReadSideEffect[0] : &:r294_16, ~m294_24 +# 294| m294_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_16 +# 294| m294_32(unknown) = Chi : total:m294_24, partial:m294_31 +# 294| r294_33(glval) = FieldAddress[i] : r294_8 +# 294| r294_34(int) = Load : &:r294_33, ~m294_29 +# 294| m294_35(int) = Store : &:r294_1, r294_34 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| m295_5(unknown) = ^CallSideEffect : ~m294_27 +# 295| m295_6(unknown) = Chi : total:m294_27, partial:m295_5 +# 295| m295_7(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_8(A *) = Convert : r295_4 +# 295| r295_9(glval) = FunctionAddress[A] : +# 295| v295_10(void) = Call : func:r295_9, this:r295_8 +# 295| m295_11(unknown) = ^CallSideEffect : ~m295_6 +# 295| m295_12(unknown) = Chi : total:m295_6, partial:m295_11 +# 295| m295_13(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_8 +# 295| m295_14(unknown) = Chi : total:m295_7, partial:m295_13 +# 295| m295_15(A *) = Store : &:r295_1, r295_8 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_9 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_8(glval) = VariableAddress[#return] : +# 291| v291_9(void) = ReturnValue : &:r291_8, m296_4 +# 291| v291_10(void) = UnmodeledUse : mu* +# 291| v291_11(void) = AliasedUse : ~m295_12 +# 291| v291_12(void) = ExitFunction : + +# 301| int main(int, char**) +# 301| Block 0 +# 301| v301_1(void) = EnterFunction : +# 301| m301_2(unknown) = AliasedDefinition : +# 301| m301_3(unknown) = InitializeNonLocal : +# 301| m301_4(unknown) = Chi : total:m301_2, partial:m301_3 +# 301| mu301_5(unknown) = UnmodeledDefinition : +# 301| r301_6(glval) = VariableAddress[argc] : +# 301| m301_7(int) = InitializeParameter[argc] : &:r301_6 +# 301| r301_8(glval) = VariableAddress[argv] : +# 301| m301_9(char **) = InitializeParameter[argv] : &:r301_8 +# 301| r301_10(char **) = Load : &:r301_8, m301_9 +# 301| m301_11(unknown) = InitializeIndirection[argv] : &:r301_10 +# 302| r302_1(glval) = FunctionAddress[unknownFunction] : +# 302| r302_2(glval) = VariableAddress[argc] : +# 302| r302_3(int) = Load : &:r302_2, m301_7 +# 302| r302_4(glval) = VariableAddress[argv] : +# 302| r302_5(char **) = Load : &:r302_4, m301_9 +# 302| v302_6(void) = Call : func:r302_1, 0:r302_3, 1:r302_5 +# 302| m302_7(unknown) = ^CallSideEffect : ~m301_4 +# 302| m302_8(unknown) = Chi : total:m301_4, partial:m302_7 +# 302| v302_9(void) = ^BufferReadSideEffect[1] : &:r302_5, ~m301_11 +# 302| m302_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r302_5 +# 302| m302_11(char *) = Chi : total:m301_11, partial:m302_10 +# 303| r303_1(glval) = FunctionAddress[unknownFunction] : +# 303| r303_2(glval) = VariableAddress[argc] : +# 303| r303_3(int) = Load : &:r303_2, m301_7 +# 303| r303_4(glval) = VariableAddress[argv] : +# 303| r303_5(char **) = Load : &:r303_4, m301_9 +# 303| v303_6(void) = Call : func:r303_1, 0:r303_3, 1:r303_5 +# 303| m303_7(unknown) = ^CallSideEffect : ~m302_8 +# 303| m303_8(unknown) = Chi : total:m302_8, partial:m303_7 +# 303| v303_9(void) = ^BufferReadSideEffect[1] : &:r303_5, ~m302_11 +# 303| m303_10(unknown) = ^BufferMayWriteSideEffect[1] : &:r303_5 +# 303| m303_11(char *) = Chi : total:m302_11, partial:m303_10 +# 304| r304_1(glval) = VariableAddress[#return] : +# 304| r304_2(glval) = VariableAddress[argv] : +# 304| r304_3(char **) = Load : &:r304_2, m301_9 +# 304| r304_4(char *) = Load : &:r304_3, ~m303_11 +# 304| r304_5(char) = Load : &:r304_4, ~m303_8 +# 304| r304_6(int) = Convert : r304_5 +# 304| m304_7(int) = Store : &:r304_1, r304_6 +# 301| v301_12(void) = ReturnIndirection[argv] : &:r301_10, ~m303_11, m303_11 +# 301| r301_13(glval) = VariableAddress[#return] : +# 301| v301_14(void) = ReturnValue : &:r301_13, m304_7 +# 301| v301_15(void) = UnmodeledUse : mu* +# 301| v301_16(void) = AliasedUse : ~m303_8 +# 301| v301_17(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected index 1e78ae87f40..f448013286b 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity_unsound.expected @@ -1,6 +1,7 @@ missingOperand unexpectedOperand duplicateOperand +| ssa.cpp:301:27:301:30 | ReturnIndirection: argv | Instruction has 2 operands with tag 'SideEffect' in function '$@'. | ssa.cpp:301:5:301:8 | IR: main | int main(int, char**) | missingPhiOperand missingOperandType duplicateChiOperand @@ -9,6 +10,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges @@ -19,6 +21,7 @@ switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated invalidOverlap +| ssa.cpp:301:27:301:30 | SideEffect | MemoryOperand 'SideEffect' has a `getDefinitionOverlap()` of 'MayPartiallyOverlap'. | ssa.cpp:301:5:301:8 | IR: main | int main(int, char**) | missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index f7e75596468..5ea3ef77968 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -280,3 +280,26 @@ void EscapedButNotConflated(bool c, Point p, int x1) { } int x = a.x; // The phi node here is not conflated } + +struct A { + int i; + A(int x) {} + A(A*) {} + A() {} +}; + +Point *NewAliasing(int x) { + Point* p = new Point; + Point* q = new Point; + int j = new A(new A(x))->i; + A* a = new A; + return p; +} + +void unknownFunction(int argc, char **argv); + +int main(int argc, char **argv) { + unknownFunction(argc, argv); + unknownFunction(argc, argv); + return **argv; // Chi chain goes through side effects from unknownFunction +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 11e502f54f1..b307db1cfc5 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -78,7 +78,7 @@ ssa.cpp: # 28| r28_9(int) = Load : &:r28_8, ~mu13_4 # 28| r28_10(int) = Add : r28_5, r28_9 # 28| m28_11(int) = Store : &:r28_1, r28_10 -# 13| v13_13(void) = ReturnIndirection : &:r13_7, ~mu13_4 +# 13| v13_13(void) = ReturnIndirection[p] : &:r13_7, ~mu13_4 # 13| r13_14(glval) = VariableAddress[#return] : # 13| v13_15(void) = ReturnValue : &:r13_14, m28_11 # 13| v13_16(void) = UnmodeledUse : mu* @@ -249,12 +249,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_11(void) = ReturnIndirection : &:r68_9, ~mu68_4 -# 68| v68_12(void) = ReturnVoid : -# 68| v68_13(void) = UnmodeledUse : mu* -# 68| v68_14(void) = AliasedUse : ~mu68_4 -# 68| v68_15(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, ~mu68_4 +# 68| v68_12(void) = ReturnVoid : +# 68| v68_13(void) = UnmodeledUse : mu* +# 68| v68_14(void) = AliasedUse : ~mu68_4 +# 68| v68_15(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -752,7 +752,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_6 # 181| r181_4(int) = Load : &:r181_3, ~mu179_4 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_9(void) = ReturnIndirection : &:r179_7, ~mu179_4 +# 179| v179_9(void) = ReturnIndirection[p] : &:r179_7, ~mu179_4 # 179| r179_10(glval) = VariableAddress[#return] : # 179| v179_11(void) = ReturnValue : &:r179_10, m181_5 # 179| v179_12(void) = UnmodeledUse : mu* @@ -795,10 +795,10 @@ ssa.cpp: # 190| r190_6(unsigned int) = Load : &:r190_5, ~mu184_4 # 186| mu186_1(unknown) = InlineAsm : ~mu184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 192| v192_1(void) = NoOp : -# 184| v184_21(void) = ReturnIndirection : &:r184_7, ~mu184_4 -# 184| v184_22(void) = ReturnIndirection : &:r184_11, ~mu184_4 -# 184| v184_23(void) = ReturnIndirection : &:r184_15, ~mu184_4 -# 184| v184_24(void) = ReturnIndirection : &:r184_19, ~mu184_4 +# 184| v184_21(void) = ReturnIndirection[a] : &:r184_7, ~mu184_4 +# 184| v184_22(void) = ReturnIndirection[b] : &:r184_11, ~mu184_4 +# 184| v184_23(void) = ReturnIndirection[c] : &:r184_15, ~mu184_4 +# 184| v184_24(void) = ReturnIndirection[d] : &:r184_19, ~mu184_4 # 184| v184_25(void) = ReturnVoid : # 184| v184_26(void) = UnmodeledUse : mu* # 184| v184_27(void) = AliasedUse : ~mu184_4 @@ -854,8 +854,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_15(void) = ReturnIndirection : &:r198_7, ~mu198_4 -# 198| v198_16(void) = ReturnIndirection : &:r198_11, ~mu198_4 +# 198| v198_15(void) = ReturnIndirection[str1] : &:r198_7, ~mu198_4 +# 198| v198_16(void) = ReturnIndirection[str2] : &:r198_11, ~mu198_4 # 198| r198_17(glval) = VariableAddress[#return] : # 198| v198_18(void) = ReturnValue : &:r198_17, m202_4 # 198| v198_19(void) = UnmodeledUse : mu* @@ -1074,8 +1074,9 @@ ssa.cpp: # 248| r248_7(unsigned long) = Mul : r248_5, r248_6 # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| mu248_9(unknown) = ^CallSideEffect : ~mu247_4 -# 248| r248_10(char *) = Convert : r248_8 -# 248| m248_11(char *) = Store : &:r248_1, r248_10 +# 248| mu248_10(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_11(char *) = Convert : r248_8 +# 248| m248_12(char *) = Store : &:r248_1, r248_11 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_6 @@ -1083,7 +1084,7 @@ ssa.cpp: # 249| mu249_5(char) = Store : &:r249_4, r249_1 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_11 +# 250| r250_3(char *) = Load : &:r250_2, m248_12 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_6 @@ -1095,9 +1096,9 @@ ssa.cpp: # 250| mu250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_11 +# 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 +# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : # 247| v247_13(void) = ReturnValue : &:r247_12, m251_4 # 247| v247_14(void) = UnmodeledUse : mu* @@ -1182,7 +1183,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_8 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4 +# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, ~mu268_4 # 268| r268_12(glval) = VariableAddress[#return] : # 268| v268_13(void) = ReturnValue : &:r268_12, m271_4 # 268| v268_14(void) = UnmodeledUse : mu* @@ -1238,3 +1239,167 @@ ssa.cpp: # 275| v275_12(void) = UnmodeledUse : mu* # 275| v275_13(void) = AliasedUse : ~mu275_4 # 275| v275_14(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| mu286_2(unknown) = AliasedDefinition : +# 286| mu286_3(unknown) = InitializeNonLocal : +# 286| mu286_4(unknown) = UnmodeledDefinition : +# 286| r286_5(glval) = InitializeThis : +# 286| r286_6(glval) = VariableAddress[x] : +# 286| m286_7(int) = InitializeParameter[x] : &:r286_6 +# 286| v286_8(void) = NoOp : +# 286| v286_9(void) = ReturnVoid : +# 286| v286_10(void) = UnmodeledUse : mu* +# 286| v286_11(void) = AliasedUse : ~mu286_4 +# 286| v286_12(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| mu287_2(unknown) = AliasedDefinition : +# 287| mu287_3(unknown) = InitializeNonLocal : +# 287| mu287_4(unknown) = UnmodeledDefinition : +# 287| r287_5(glval) = InitializeThis : +# 287| r287_6(glval) = VariableAddress[p#0] : +# 287| m287_7(A *) = InitializeParameter[p#0] : &:r287_6 +# 287| r287_8(A *) = Load : &:r287_6, m287_7 +# 287| mu287_9(unknown) = InitializeIndirection[p#0] : &:r287_8 +# 287| v287_10(void) = NoOp : +# 287| v287_11(void) = ReturnIndirection[p#0] : &:r287_8, ~mu287_4 +# 287| v287_12(void) = ReturnVoid : +# 287| v287_13(void) = UnmodeledUse : mu* +# 287| v287_14(void) = AliasedUse : ~mu287_4 +# 287| v287_15(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| mu288_2(unknown) = AliasedDefinition : +# 288| mu288_3(unknown) = InitializeNonLocal : +# 288| mu288_4(unknown) = UnmodeledDefinition : +# 288| r288_5(glval) = InitializeThis : +# 288| v288_6(void) = NoOp : +# 288| v288_7(void) = ReturnVoid : +# 288| v288_8(void) = UnmodeledUse : mu* +# 288| v288_9(void) = AliasedUse : ~mu288_4 +# 288| v288_10(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| mu291_2(unknown) = AliasedDefinition : +# 291| mu291_3(unknown) = InitializeNonLocal : +# 291| mu291_4(unknown) = UnmodeledDefinition : +# 291| r291_5(glval) = VariableAddress[x] : +# 291| m291_6(int) = InitializeParameter[x] : &:r291_5 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 +# 292| mu292_6(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 +# 293| mu293_6(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_6(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| mu294_12(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_13(unknown) = ^InitializeDynamicAllocation : &:r294_11 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_6 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| mu294_19(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_20(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| v294_21(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| mu294_22(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_14, ~mu291_4 +# 294| mu294_25(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| r294_26(glval) = FieldAddress[i] : r294_7 +# 294| r294_27(int) = Load : &:r294_26, ~mu291_4 +# 294| m294_28(int) = Store : &:r294_1, r294_27 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_6(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| mu295_10(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_12(A *) = Store : &:r295_1, r295_7 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_7(glval) = VariableAddress[#return] : +# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 +# 291| v291_9(void) = UnmodeledUse : mu* +# 291| v291_10(void) = AliasedUse : ~mu291_4 +# 291| v291_11(void) = ExitFunction : + +# 301| int main(int, char**) +# 301| Block 0 +# 301| v301_1(void) = EnterFunction : +# 301| mu301_2(unknown) = AliasedDefinition : +# 301| mu301_3(unknown) = InitializeNonLocal : +# 301| mu301_4(unknown) = UnmodeledDefinition : +# 301| r301_5(glval) = VariableAddress[argc] : +# 301| m301_6(int) = InitializeParameter[argc] : &:r301_5 +# 301| r301_7(glval) = VariableAddress[argv] : +# 301| m301_8(char **) = InitializeParameter[argv] : &:r301_7 +# 301| r301_9(char **) = Load : &:r301_7, m301_8 +# 301| mu301_10(unknown) = InitializeIndirection[argv] : &:r301_9 +# 302| r302_1(glval) = FunctionAddress[unknownFunction] : +# 302| r302_2(glval) = VariableAddress[argc] : +# 302| r302_3(int) = Load : &:r302_2, m301_6 +# 302| r302_4(glval) = VariableAddress[argv] : +# 302| r302_5(char **) = Load : &:r302_4, m301_8 +# 302| v302_6(void) = Call : func:r302_1, 0:r302_3, 1:r302_5 +# 302| mu302_7(unknown) = ^CallSideEffect : ~mu301_4 +# 302| v302_8(void) = ^BufferReadSideEffect[1] : &:r302_5, ~mu301_4 +# 302| mu302_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r302_5 +# 303| r303_1(glval) = FunctionAddress[unknownFunction] : +# 303| r303_2(glval) = VariableAddress[argc] : +# 303| r303_3(int) = Load : &:r303_2, m301_6 +# 303| r303_4(glval) = VariableAddress[argv] : +# 303| r303_5(char **) = Load : &:r303_4, m301_8 +# 303| v303_6(void) = Call : func:r303_1, 0:r303_3, 1:r303_5 +# 303| mu303_7(unknown) = ^CallSideEffect : ~mu301_4 +# 303| v303_8(void) = ^BufferReadSideEffect[1] : &:r303_5, ~mu301_4 +# 303| mu303_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r303_5 +# 304| r304_1(glval) = VariableAddress[#return] : +# 304| r304_2(glval) = VariableAddress[argv] : +# 304| r304_3(char **) = Load : &:r304_2, m301_8 +# 304| r304_4(char *) = Load : &:r304_3, ~mu301_4 +# 304| r304_5(char) = Load : &:r304_4, ~mu301_4 +# 304| r304_6(int) = Convert : r304_5 +# 304| m304_7(int) = Store : &:r304_1, r304_6 +# 301| v301_11(void) = ReturnIndirection[argv] : &:r301_9, ~mu301_4 +# 301| r301_12(glval) = VariableAddress[#return] : +# 301| v301_13(void) = ReturnValue : &:r301_12, m304_7 +# 301| v301_14(void) = UnmodeledUse : mu* +# 301| v301_15(void) = AliasedUse : ~mu301_4 +# 301| v301_16(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected index 11e502f54f1..b307db1cfc5 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir_unsound.expected @@ -78,7 +78,7 @@ ssa.cpp: # 28| r28_9(int) = Load : &:r28_8, ~mu13_4 # 28| r28_10(int) = Add : r28_5, r28_9 # 28| m28_11(int) = Store : &:r28_1, r28_10 -# 13| v13_13(void) = ReturnIndirection : &:r13_7, ~mu13_4 +# 13| v13_13(void) = ReturnIndirection[p] : &:r13_7, ~mu13_4 # 13| r13_14(glval) = VariableAddress[#return] : # 13| v13_15(void) = ReturnValue : &:r13_14, m28_11 # 13| v13_16(void) = UnmodeledUse : mu* @@ -249,12 +249,12 @@ ssa.cpp: #-----| Goto (back edge) -> Block 1 # 71| Block 3 -# 71| v71_1(void) = NoOp : -# 68| v68_11(void) = ReturnIndirection : &:r68_9, ~mu68_4 -# 68| v68_12(void) = ReturnVoid : -# 68| v68_13(void) = UnmodeledUse : mu* -# 68| v68_14(void) = AliasedUse : ~mu68_4 -# 68| v68_15(void) = ExitFunction : +# 71| v71_1(void) = NoOp : +# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, ~mu68_4 +# 68| v68_12(void) = ReturnVoid : +# 68| v68_13(void) = UnmodeledUse : mu* +# 68| v68_14(void) = AliasedUse : ~mu68_4 +# 68| v68_15(void) = ExitFunction : # 75| void ScalarPhi(bool) # 75| Block 0 @@ -752,7 +752,7 @@ ssa.cpp: # 181| r181_3(int *) = Load : &:r181_2, m179_6 # 181| r181_4(int) = Load : &:r181_3, ~mu179_4 # 181| m181_5(int) = Store : &:r181_1, r181_4 -# 179| v179_9(void) = ReturnIndirection : &:r179_7, ~mu179_4 +# 179| v179_9(void) = ReturnIndirection[p] : &:r179_7, ~mu179_4 # 179| r179_10(glval) = VariableAddress[#return] : # 179| v179_11(void) = ReturnValue : &:r179_10, m181_5 # 179| v179_12(void) = UnmodeledUse : mu* @@ -795,10 +795,10 @@ ssa.cpp: # 190| r190_6(unsigned int) = Load : &:r190_5, ~mu184_4 # 186| mu186_1(unknown) = InlineAsm : ~mu184_4, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6 # 192| v192_1(void) = NoOp : -# 184| v184_21(void) = ReturnIndirection : &:r184_7, ~mu184_4 -# 184| v184_22(void) = ReturnIndirection : &:r184_11, ~mu184_4 -# 184| v184_23(void) = ReturnIndirection : &:r184_15, ~mu184_4 -# 184| v184_24(void) = ReturnIndirection : &:r184_19, ~mu184_4 +# 184| v184_21(void) = ReturnIndirection[a] : &:r184_7, ~mu184_4 +# 184| v184_22(void) = ReturnIndirection[b] : &:r184_11, ~mu184_4 +# 184| v184_23(void) = ReturnIndirection[c] : &:r184_15, ~mu184_4 +# 184| v184_24(void) = ReturnIndirection[d] : &:r184_19, ~mu184_4 # 184| v184_25(void) = ReturnVoid : # 184| v184_26(void) = UnmodeledUse : mu* # 184| v184_27(void) = AliasedUse : ~mu184_4 @@ -854,8 +854,8 @@ ssa.cpp: # 202| r202_2(glval) = VariableAddress[ret] : # 202| r202_3(int) = Load : &:r202_2, m201_8 # 202| m202_4(int) = Store : &:r202_1, r202_3 -# 198| v198_15(void) = ReturnIndirection : &:r198_7, ~mu198_4 -# 198| v198_16(void) = ReturnIndirection : &:r198_11, ~mu198_4 +# 198| v198_15(void) = ReturnIndirection[str1] : &:r198_7, ~mu198_4 +# 198| v198_16(void) = ReturnIndirection[str2] : &:r198_11, ~mu198_4 # 198| r198_17(glval) = VariableAddress[#return] : # 198| v198_18(void) = ReturnValue : &:r198_17, m202_4 # 198| v198_19(void) = UnmodeledUse : mu* @@ -1074,8 +1074,9 @@ ssa.cpp: # 248| r248_7(unsigned long) = Mul : r248_5, r248_6 # 248| r248_8(void *) = Call : func:r248_2, 0:r248_7 # 248| mu248_9(unknown) = ^CallSideEffect : ~mu247_4 -# 248| r248_10(char *) = Convert : r248_8 -# 248| m248_11(char *) = Store : &:r248_1, r248_10 +# 248| mu248_10(unknown) = ^InitializeDynamicAllocation : &:r248_8 +# 248| r248_11(char *) = Convert : r248_8 +# 248| m248_12(char *) = Store : &:r248_1, r248_11 # 249| r249_1(char) = Constant[97] : # 249| r249_2(glval) = VariableAddress[src] : # 249| r249_3(char *) = Load : &:r249_2, m247_6 @@ -1083,7 +1084,7 @@ ssa.cpp: # 249| mu249_5(char) = Store : &:r249_4, r249_1 # 250| r250_1(glval) = FunctionAddress[memcpy] : # 250| r250_2(glval) = VariableAddress[dst] : -# 250| r250_3(char *) = Load : &:r250_2, m248_11 +# 250| r250_3(char *) = Load : &:r250_2, m248_12 # 250| r250_4(void *) = Convert : r250_3 # 250| r250_5(glval) = VariableAddress[src] : # 250| r250_6(char *) = Load : &:r250_5, m247_6 @@ -1095,9 +1096,9 @@ ssa.cpp: # 250| mu250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9 # 251| r251_1(glval) = VariableAddress[#return] : # 251| r251_2(glval) = VariableAddress[dst] : -# 251| r251_3(char *) = Load : &:r251_2, m248_11 +# 251| r251_3(char *) = Load : &:r251_2, m248_12 # 251| m251_4(char *) = Store : &:r251_1, r251_3 -# 247| v247_11(void) = ReturnIndirection : &:r247_7, ~mu247_4 +# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, ~mu247_4 # 247| r247_12(glval) = VariableAddress[#return] : # 247| v247_13(void) = ReturnValue : &:r247_12, m251_4 # 247| v247_14(void) = UnmodeledUse : mu* @@ -1182,7 +1183,7 @@ ssa.cpp: # 271| r271_2(glval) = VariableAddress[buf] : # 271| r271_3(void *) = Load : &:r271_2, m269_8 # 271| m271_4(void *) = Store : &:r271_1, r271_3 -# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4 +# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, ~mu268_4 # 268| r268_12(glval) = VariableAddress[#return] : # 268| v268_13(void) = ReturnValue : &:r268_12, m271_4 # 268| v268_14(void) = UnmodeledUse : mu* @@ -1238,3 +1239,167 @@ ssa.cpp: # 275| v275_12(void) = UnmodeledUse : mu* # 275| v275_13(void) = AliasedUse : ~mu275_4 # 275| v275_14(void) = ExitFunction : + +# 286| void A::A(int) +# 286| Block 0 +# 286| v286_1(void) = EnterFunction : +# 286| mu286_2(unknown) = AliasedDefinition : +# 286| mu286_3(unknown) = InitializeNonLocal : +# 286| mu286_4(unknown) = UnmodeledDefinition : +# 286| r286_5(glval) = InitializeThis : +# 286| r286_6(glval) = VariableAddress[x] : +# 286| m286_7(int) = InitializeParameter[x] : &:r286_6 +# 286| v286_8(void) = NoOp : +# 286| v286_9(void) = ReturnVoid : +# 286| v286_10(void) = UnmodeledUse : mu* +# 286| v286_11(void) = AliasedUse : ~mu286_4 +# 286| v286_12(void) = ExitFunction : + +# 287| void A::A(A*) +# 287| Block 0 +# 287| v287_1(void) = EnterFunction : +# 287| mu287_2(unknown) = AliasedDefinition : +# 287| mu287_3(unknown) = InitializeNonLocal : +# 287| mu287_4(unknown) = UnmodeledDefinition : +# 287| r287_5(glval) = InitializeThis : +# 287| r287_6(glval) = VariableAddress[p#0] : +# 287| m287_7(A *) = InitializeParameter[p#0] : &:r287_6 +# 287| r287_8(A *) = Load : &:r287_6, m287_7 +# 287| mu287_9(unknown) = InitializeIndirection[p#0] : &:r287_8 +# 287| v287_10(void) = NoOp : +# 287| v287_11(void) = ReturnIndirection[p#0] : &:r287_8, ~mu287_4 +# 287| v287_12(void) = ReturnVoid : +# 287| v287_13(void) = UnmodeledUse : mu* +# 287| v287_14(void) = AliasedUse : ~mu287_4 +# 287| v287_15(void) = ExitFunction : + +# 288| void A::A() +# 288| Block 0 +# 288| v288_1(void) = EnterFunction : +# 288| mu288_2(unknown) = AliasedDefinition : +# 288| mu288_3(unknown) = InitializeNonLocal : +# 288| mu288_4(unknown) = UnmodeledDefinition : +# 288| r288_5(glval) = InitializeThis : +# 288| v288_6(void) = NoOp : +# 288| v288_7(void) = ReturnVoid : +# 288| v288_8(void) = UnmodeledUse : mu* +# 288| v288_9(void) = AliasedUse : ~mu288_4 +# 288| v288_10(void) = ExitFunction : + +# 291| Point* NewAliasing(int) +# 291| Block 0 +# 291| v291_1(void) = EnterFunction : +# 291| mu291_2(unknown) = AliasedDefinition : +# 291| mu291_3(unknown) = InitializeNonLocal : +# 291| mu291_4(unknown) = UnmodeledDefinition : +# 291| r291_5(glval) = VariableAddress[x] : +# 291| m291_6(int) = InitializeParameter[x] : &:r291_5 +# 292| r292_1(glval) = VariableAddress[p] : +# 292| r292_2(glval) = FunctionAddress[operator new] : +# 292| r292_3(unsigned long) = Constant[8] : +# 292| r292_4(void *) = Call : func:r292_2, 0:r292_3 +# 292| mu292_5(unknown) = ^CallSideEffect : ~mu291_4 +# 292| mu292_6(unknown) = ^InitializeDynamicAllocation : &:r292_4 +# 292| r292_7(Point *) = Convert : r292_4 +# 292| m292_8(Point *) = Store : &:r292_1, r292_7 +# 293| r293_1(glval) = VariableAddress[q] : +# 293| r293_2(glval) = FunctionAddress[operator new] : +# 293| r293_3(unsigned long) = Constant[8] : +# 293| r293_4(void *) = Call : func:r293_2, 0:r293_3 +# 293| mu293_5(unknown) = ^CallSideEffect : ~mu291_4 +# 293| mu293_6(unknown) = ^InitializeDynamicAllocation : &:r293_4 +# 293| r293_7(Point *) = Convert : r293_4 +# 293| m293_8(Point *) = Store : &:r293_1, r293_7 +# 294| r294_1(glval) = VariableAddress[j] : +# 294| r294_2(glval) = FunctionAddress[operator new] : +# 294| r294_3(unsigned long) = Constant[4] : +# 294| r294_4(void *) = Call : func:r294_2, 0:r294_3 +# 294| mu294_5(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_6(unknown) = ^InitializeDynamicAllocation : &:r294_4 +# 294| r294_7(A *) = Convert : r294_4 +# 294| r294_8(glval) = FunctionAddress[A] : +# 294| r294_9(glval) = FunctionAddress[operator new] : +# 294| r294_10(unsigned long) = Constant[4] : +# 294| r294_11(void *) = Call : func:r294_9, 0:r294_10 +# 294| mu294_12(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_13(unknown) = ^InitializeDynamicAllocation : &:r294_11 +# 294| r294_14(A *) = Convert : r294_11 +# 294| r294_15(glval) = FunctionAddress[A] : +# 294| r294_16(glval) = VariableAddress[x] : +# 294| r294_17(int) = Load : &:r294_16, m291_6 +# 294| v294_18(void) = Call : func:r294_15, this:r294_14, 0:r294_17 +# 294| mu294_19(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_20(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_14 +# 294| v294_21(void) = Call : func:r294_8, this:r294_7, 0:r294_14 +# 294| mu294_22(unknown) = ^CallSideEffect : ~mu291_4 +# 294| mu294_23(A) = ^IndirectMayWriteSideEffect[-1] : &:r294_7 +# 294| v294_24(void) = ^BufferReadSideEffect[0] : &:r294_14, ~mu291_4 +# 294| mu294_25(unknown) = ^BufferMayWriteSideEffect[0] : &:r294_14 +# 294| r294_26(glval) = FieldAddress[i] : r294_7 +# 294| r294_27(int) = Load : &:r294_26, ~mu291_4 +# 294| m294_28(int) = Store : &:r294_1, r294_27 +# 295| r295_1(glval) = VariableAddress[a] : +# 295| r295_2(glval) = FunctionAddress[operator new] : +# 295| r295_3(unsigned long) = Constant[4] : +# 295| r295_4(void *) = Call : func:r295_2, 0:r295_3 +# 295| mu295_5(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_6(unknown) = ^InitializeDynamicAllocation : &:r295_4 +# 295| r295_7(A *) = Convert : r295_4 +# 295| r295_8(glval) = FunctionAddress[A] : +# 295| v295_9(void) = Call : func:r295_8, this:r295_7 +# 295| mu295_10(unknown) = ^CallSideEffect : ~mu291_4 +# 295| mu295_11(A) = ^IndirectMayWriteSideEffect[-1] : &:r295_7 +# 295| m295_12(A *) = Store : &:r295_1, r295_7 +# 296| r296_1(glval) = VariableAddress[#return] : +# 296| r296_2(glval) = VariableAddress[p] : +# 296| r296_3(Point *) = Load : &:r296_2, m292_8 +# 296| m296_4(Point *) = Store : &:r296_1, r296_3 +# 291| r291_7(glval) = VariableAddress[#return] : +# 291| v291_8(void) = ReturnValue : &:r291_7, m296_4 +# 291| v291_9(void) = UnmodeledUse : mu* +# 291| v291_10(void) = AliasedUse : ~mu291_4 +# 291| v291_11(void) = ExitFunction : + +# 301| int main(int, char**) +# 301| Block 0 +# 301| v301_1(void) = EnterFunction : +# 301| mu301_2(unknown) = AliasedDefinition : +# 301| mu301_3(unknown) = InitializeNonLocal : +# 301| mu301_4(unknown) = UnmodeledDefinition : +# 301| r301_5(glval) = VariableAddress[argc] : +# 301| m301_6(int) = InitializeParameter[argc] : &:r301_5 +# 301| r301_7(glval) = VariableAddress[argv] : +# 301| m301_8(char **) = InitializeParameter[argv] : &:r301_7 +# 301| r301_9(char **) = Load : &:r301_7, m301_8 +# 301| mu301_10(unknown) = InitializeIndirection[argv] : &:r301_9 +# 302| r302_1(glval) = FunctionAddress[unknownFunction] : +# 302| r302_2(glval) = VariableAddress[argc] : +# 302| r302_3(int) = Load : &:r302_2, m301_6 +# 302| r302_4(glval) = VariableAddress[argv] : +# 302| r302_5(char **) = Load : &:r302_4, m301_8 +# 302| v302_6(void) = Call : func:r302_1, 0:r302_3, 1:r302_5 +# 302| mu302_7(unknown) = ^CallSideEffect : ~mu301_4 +# 302| v302_8(void) = ^BufferReadSideEffect[1] : &:r302_5, ~mu301_4 +# 302| mu302_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r302_5 +# 303| r303_1(glval) = FunctionAddress[unknownFunction] : +# 303| r303_2(glval) = VariableAddress[argc] : +# 303| r303_3(int) = Load : &:r303_2, m301_6 +# 303| r303_4(glval) = VariableAddress[argv] : +# 303| r303_5(char **) = Load : &:r303_4, m301_8 +# 303| v303_6(void) = Call : func:r303_1, 0:r303_3, 1:r303_5 +# 303| mu303_7(unknown) = ^CallSideEffect : ~mu301_4 +# 303| v303_8(void) = ^BufferReadSideEffect[1] : &:r303_5, ~mu301_4 +# 303| mu303_9(unknown) = ^BufferMayWriteSideEffect[1] : &:r303_5 +# 304| r304_1(glval) = VariableAddress[#return] : +# 304| r304_2(glval) = VariableAddress[argv] : +# 304| r304_3(char **) = Load : &:r304_2, m301_8 +# 304| r304_4(char *) = Load : &:r304_3, ~mu301_4 +# 304| r304_5(char) = Load : &:r304_4, ~mu301_4 +# 304| r304_6(int) = Convert : r304_5 +# 304| m304_7(int) = Store : &:r304_1, r304_6 +# 301| v301_11(void) = ReturnIndirection[argv] : &:r301_9, ~mu301_4 +# 301| r301_12(glval) = VariableAddress[#return] : +# 301| v301_13(void) = ReturnValue : &:r301_12, m304_7 +# 301| v301_14(void) = UnmodeledUse : mu* +# 301| v301_15(void) = AliasedUse : ~mu301_4 +# 301| v301_16(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected index 1e78ae87f40..e2db1e65034 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity_unsound.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/ir/types/complex.c b/cpp/ql/test/library-tests/ir/types/complex.c new file mode 100644 index 00000000000..450f5de9e65 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/complex.c @@ -0,0 +1,15 @@ +void Complex(void) { + _Complex float cf; //$irtype=cfloat8 + _Complex double cd; //$irtype=cfloat16 + _Complex long double cld; //$irtype=cfloat32 + // _Complex __float128 cf128; +} + +void Imaginary(void) { + _Imaginary float jf; //$irtype=ifloat4 + _Imaginary double jd; //$irtype=ifloat8 + _Imaginary long double jld; //$irtype=ifloat16 + // _Imaginary __float128 jf128; +} + +// semmle-extractor-options: --microsoft --edg --c99 diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.cpp b/cpp/ql/test/library-tests/ir/types/irtypes.cpp new file mode 100644 index 00000000000..321382567b7 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/irtypes.cpp @@ -0,0 +1,65 @@ +struct A { + int f_a; +}; + +struct B { + double f_a; + float f_b; +}; + +enum E { + Zero, + One, + Two, + Three +}; + +enum class ScopedE { + Zero, + One, + Two, + Three +}; + +void IRTypes() { + char c; //$irtype=int1 + signed char sc; //$irtype=int1 + unsigned char uc; //$irtype=uint1 + short s; //$irtype=int2 + signed short ss; //$irtype=int2 + unsigned short us; //$irtype=uint2 + int i; //$irtype=int4 + signed int si; //$irtype=int4 + unsigned int ui; //$irtype=uint4 + long l; //$irtype=int8 + signed long sl; //$irtype=int8 + unsigned long ul; //$irtype=uint8 + long long ll; //$irtype=int8 + signed long long sll; //$irtype=int8 + unsigned long long ull; //$irtype=uint8 + bool b; //$irtype=bool1 + float f; //$irtype=float4 + double d; //$irtype=float8 + long double ld; //$irtype=float16 + __float128 f128; //$irtype=float16 + + wchar_t wc; //$irtype=uint4 +// char8_t c8; //$irtype=uint1 + char16_t c16; //$irtype=uint2 + char32_t c32; //$irtype=uint4 + + int* pi; //$irtype=addr8 + int& ri = i; //$irtype=addr8 + void (*pfn)() = nullptr; //$irtype=func8 + void (&rfn)() = IRTypes; //$irtype=func8 + + A s_a; //$irtype=opaque4{A} + B s_b; //$irtype=opaque16{B} + + E e; //$irtype=uint4 + ScopedE se; //$irtype=uint4 + + B a_b[10]; //$irtype=opaque160{B[10]} +} + +// semmle-extractor-options: -std=c++17 --clang diff --git a/javascript/ql/test/library-tests/FileTypes/test.js b/cpp/ql/test/library-tests/ir/types/irtypes.expected similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.js rename to cpp/ql/test/library-tests/ir/types/irtypes.expected diff --git a/cpp/ql/test/library-tests/ir/types/irtypes.ql b/cpp/ql/test/library-tests/ir/types/irtypes.ql new file mode 100644 index 00000000000..56a7666458b --- /dev/null +++ b/cpp/ql/test/library-tests/ir/types/irtypes.ql @@ -0,0 +1,18 @@ +private import cpp +private import semmle.code.cpp.ir.implementation.raw.IR +import TestUtilities.InlineExpectationsTest + +class IRTypesTest extends InlineExpectationsTest { + IRTypesTest() { this = "IRTypesTest" } + + override string getARelevantTag() { result = "irtype" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(IRUserVariable irVar | + location = irVar.getLocation() and + element = irVar.toString() and + tag = "irtype" and + value = irVar.getIRType().toString() + ) + } +} diff --git a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected index be768a4a82f..78ff3edde3d 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/RangeAnalysis.expected @@ -35,7 +35,7 @@ | test.cpp:97:10:97:10 | Load: x | file://:0:0:0:0 | 0 | 1 | false | CompareLT: ... < ... | test.cpp:94:7:94:11 | test.cpp:94:7:94:11 | | test.cpp:100:10:100:10 | Load: x | file://:0:0:0:0 | 0 | 1 | true | CompareLE: ... <= ... | test.cpp:99:7:99:12 | test.cpp:99:7:99:12 | | test.cpp:102:10:102:10 | Load: x | file://:0:0:0:0 | 0 | 2 | false | CompareLE: ... <= ... | test.cpp:99:7:99:12 | test.cpp:99:7:99:12 | -| test.cpp:107:5:107:10 | Phi: test10 | test.cpp:114:3:114:6 | Phi: call to sink | -1 | true | CompareLT: ... < ... | test.cpp:115:18:115:22 | test.cpp:115:18:115:22 | +| test.cpp:117:10:117:10 | Load: i | test.cpp:114:3:114:6 | Phi: call to sink | -1 | true | CompareLT: ... < ... | test.cpp:116:7:116:11 | test.cpp:116:7:116:11 | | test.cpp:130:10:130:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:140:10:140:10 | Store: i | file://:0:0:0:0 | 0 | 1 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 | | test.cpp:140:10:140:10 | Store: i | test.cpp:135:16:135:16 | InitializeParameter: x | 0 | false | CompareLT: ... < ... | test.cpp:139:11:139:15 | test.cpp:139:11:139:15 | diff --git a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp index d31de1d2b80..87653c2fa43 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp +++ b/cpp/ql/test/library-tests/rangeanalysis/rangeanalysis/test.cpp @@ -104,7 +104,7 @@ void test9(int x) { } // Phi nodes as bounds -int test10(int y, int z, bool use_y) { +void test10(int y, int z, bool use_y) { int x; if(use_y) { x = y; @@ -112,9 +112,9 @@ int test10(int y, int z, bool use_y) { x = z; } sink(); - for(int i = 0; i < x; i++) { - return i; - } + int i = source(); + if (i < x) + sink(i); } // Irreducible CFGs diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 362983363cc..83b5d2bfa80 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -30,7 +30,6 @@ missingOperand unexpectedOperand duplicateOperand missingPhiOperand -| cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | missingOperandType duplicateChiOperand sideEffectWithoutPrimary @@ -83,50 +82,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -213,50 +210,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -361,50 +356,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -463,50 +456,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | @@ -539,6 +530,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected new file mode 100644 index 00000000000..52963b455e2 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected @@ -0,0 +1,98 @@ +uniqueEnclosingCallable +| enum.c:2:6:2:6 | 1 | Node should have one enclosing callable but has 0. | +| enum.c:2:6:2:10 | ... + ... | Node should have one enclosing callable but has 0. | +| enum.c:2:10:2:10 | 1 | Node should have one enclosing callable but has 0. | +| misc.c:11:17:11:17 | 1 | Node should have one enclosing callable but has 0. | +| misc.c:11:17:11:21 | ... + ... | Node should have one enclosing callable but has 0. | +| misc.c:11:21:11:21 | 2 | Node should have one enclosing callable but has 0. | +| misc.c:210:24:210:24 | 0 | Node should have one enclosing callable but has 0. | +| misc.c:210:24:210:28 | ... + ... | Node should have one enclosing callable but has 0. | +| misc.c:210:28:210:28 | 1 | Node should have one enclosing callable but has 0. | +uniqueTypeBound +| bad_asts.cpp:19:10:19:10 | constructor init of field x [post-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field x [pre-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [post-this] | Node should have one type bound but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [pre-this] | Node should have one type bound but has 0. | +| cpp17.cpp:15:5:15:45 | call to unknown function | Node should have one type bound but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [post-this] | Node should have one type bound but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [pre-this] | Node should have one type bound but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [post-this] | Node should have one type bound but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [pre-this] | Node should have one type bound but has 0. | +uniqueTypeRepr +| bad_asts.cpp:19:10:19:10 | constructor init of field x [post-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field x [pre-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [post-this] | Node should have one type representation but has 0. | +| bad_asts.cpp:19:10:19:10 | constructor init of field y [pre-this] | Node should have one type representation but has 0. | +| cpp17.cpp:15:5:15:45 | call to unknown function | Node should have one type representation but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [post-this] | Node should have one type representation but has 0. | +| ir.cpp:784:15:784:15 | constructor init of field middlevb2_s [pre-this] | Node should have one type representation but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [post-this] | Node should have one type representation but has 0. | +| static_init_templates.cpp:240:7:240:7 | constructor init of field mcc [pre-this] | Node should have one type representation but has 0. | +uniqueNodeLocation +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| cpp11.cpp:82:17:82:55 | call to Val | Node should have one location but has 2. | +| cpp11.cpp:82:17:82:55 | call to Val | Node should have one location but has 2. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| file://:0:0:0:0 | call to PolymorphicBase | Node should have one location but has 2. | +| file://:0:0:0:0 | call to PolymorphicDerived | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Val | Node should have one location but has 2. | +| file://:0:0:0:0 | call to Val | Node should have one location but has 2. | +| file://:0:0:0:0 | call to exn1 | Node should have one location but has 2. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| ir.cpp:850:19:850:19 | call to PolymorphicBase | Node should have one location but has 2. | +| ir.cpp:851:22:851:22 | call to PolymorphicDerived | Node should have one location but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| try_catch.cpp:13:5:13:16 | call to exn1 | Node should have one location but has 2. | +missingLocation +| Nodes without location: 2 | +uniqueNodeToString +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +missingToString +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate +| builtin.cpp:15:31:15:35 | * ... | ArgumentNode is missing PostUpdateNode. | +| cpp11.cpp:77:5:77:17 | unaryFunction | ArgumentNode is missing PostUpdateNode. | +| destructors.cpp:52:14:52:16 | ref | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:623:5:623:5 | r | ArgumentNode is missing PostUpdateNode. | +| ir.cpp:625:5:625:5 | s | ArgumentNode is missing PostUpdateNode. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql new file mode 100644 index 00000000000..4304a961abe --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected new file mode 100644 index 00000000000..f3e74c759b6 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -0,0 +1,795 @@ +uniqueEnclosingCallable +uniqueTypeBound +uniqueTypeRepr +uniqueNodeLocation +| aggregateinitializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| aggregateinitializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| allocators.cpp:14:5:14:8 | AliasedDefinition | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | AliasedUse | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Chi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | EnterFunction | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | ExitFunction | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | InitializeNonLocal | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | ReturnValue | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | UnmodeledDefinition | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | UnmodeledUse | Node should have one location but has 4. | +| allocators.cpp:14:5:14:8 | VariableAddress | Node should have one location but has 4. | +| array_delete.cpp:5:6:5:6 | AliasedDefinition | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | AliasedUse | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | Chi | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | EnterFunction | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | ExitFunction | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | InitializeNonLocal | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | ReturnVoid | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | UnmodeledDefinition | Node should have one location but has 14. | +| array_delete.cpp:5:6:5:6 | UnmodeledUse | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| assignexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| break_labels.c:2:5:2:5 | AliasedDefinition | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | AliasedUse | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Chi | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | EnterFunction | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | ExitFunction | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | InitializeNonLocal | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | ReturnVoid | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | UnmodeledDefinition | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | UnmodeledUse | Node should have one location but has 20. | +| break_labels.c:2:5:2:5 | Unreached | Node should have one location but has 20. | +| break_labels.c:2:11:2:11 | VariableAddress | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | +| conditional_destructors.cpp:29:6:29:7 | AliasedDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | AliasedUse | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | Chi | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:29:6:29:7 | UnmodeledUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | AliasedUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Chi | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | UnmodeledUse | Node should have one location but has 2. | +| conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. | +| constmemberaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | +| constmemberaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| constmemberaccess.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| constructorinitializer.cpp:3:9:3:9 | i | Node should have one location but has 2. | +| constructorinitializer.cpp:3:9:3:9 | x | Node should have one location but has 2. | +| constructorinitializer.cpp:3:16:3:16 | j | Node should have one location but has 2. | +| constructorinitializer.cpp:3:16:3:16 | y | Node should have one location but has 2. | +| constructorinitializer.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| constructorinitializer.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 14. | +| defconstructornewexpr.cpp:3:6:3:6 | UnmodeledUse | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 14. | +| defdestructordeleteexpr.cpp:3:6:3:6 | UnmodeledUse | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| deleteexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| dostmt.c:8:6:8:18 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | Chi | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | UnmodeledUse | Node should have one location but has 4. | +| dostmt.c:8:6:8:18 | Unreached | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | Chi | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | UnmodeledUse | Node should have one location but has 4. | +| dostmt.c:16:6:16:18 | Unreached | Node should have one location but has 4. | +| dostmt.c:25:6:25:18 | AliasedDefinition | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | Chi | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | EnterFunction | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | InitializeNonLocal | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | UnmodeledDefinition | Node should have one location but has 2. | +| dostmt.c:25:6:25:18 | Unreached | Node should have one location but has 2. | +| dostmt.c:32:6:32:11 | AliasedDefinition | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | AliasedUse | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | Chi | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | EnterFunction | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | ExitFunction | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | InitializeNonLocal | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | ReturnVoid | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | UnmodeledDefinition | Node should have one location but has 4. | +| dostmt.c:32:6:32:11 | UnmodeledUse | Node should have one location but has 4. | +| duff.c:2:6:2:6 | AliasedDefinition | Node should have one location but has 20. | +| duff.c:2:6:2:6 | AliasedUse | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Chi | Node should have one location but has 20. | +| duff.c:2:6:2:6 | EnterFunction | Node should have one location but has 20. | +| duff.c:2:6:2:6 | ExitFunction | Node should have one location but has 20. | +| duff.c:2:6:2:6 | InitializeNonLocal | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | +| duff.c:2:6:2:6 | ReturnVoid | Node should have one location but has 20. | +| duff.c:2:6:2:6 | UnmodeledDefinition | Node should have one location but has 20. | +| duff.c:2:6:2:6 | UnmodeledUse | Node should have one location but has 20. | +| duff.c:2:6:2:6 | Unreached | Node should have one location but has 20. | +| duff.c:2:12:2:12 | VariableAddress | Node should have one location but has 4. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | i | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| duff.c:2:12:2:12 | x | Node should have one location but has 4. | +| dummyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| dummyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| emptyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| enum.c:5:5:5:5 | AliasedDefinition | Node should have one location but has 20. | +| enum.c:5:5:5:5 | AliasedUse | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Chi | Node should have one location but has 20. | +| enum.c:5:5:5:5 | EnterFunction | Node should have one location but has 20. | +| enum.c:5:5:5:5 | ExitFunction | Node should have one location but has 20. | +| enum.c:5:5:5:5 | InitializeNonLocal | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | +| enum.c:5:5:5:5 | ReturnVoid | Node should have one location but has 20. | +| enum.c:5:5:5:5 | UnmodeledDefinition | Node should have one location but has 20. | +| enum.c:5:5:5:5 | UnmodeledUse | Node should have one location but has 20. | +| enum.c:5:5:5:5 | Unreached | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| exprstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| fieldaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | +| fieldaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| fieldaccess.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| file://:0:0:0:0 | InitializeIndirection | Node should have one location but has 0. | +| file://:0:0:0:0 | Load | Node should have one location but has 0. | +| file://:0:0:0:0 | ReturnIndirection | Node should have one location but has 0. | +| file://:0:0:0:0 | VariableAddress | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#0 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#1 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#2 | Node should have one location but has 0. | +| file://:0:0:0:0 | p#3 | Node should have one location but has 0. | +| forstmt.cpp:1:6:1:7 | AliasedDefinition | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | AliasedUse | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | Chi | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | UnmodeledDefinition | Node should have one location but has 2. | +| forstmt.cpp:1:6:1:7 | UnmodeledUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | AliasedUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Chi | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | UnmodeledDefinition | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | UnmodeledUse | Node should have one location but has 2. | +| forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. | +| ifelsestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| ifelsestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | AliasedDefinition | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | AliasedUse | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | Chi | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | EnterFunction | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | ExitFunction | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | ReturnVoid | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | UnmodeledUse | Node should have one location but has 3. | +| ifelsestmt.c:11:6:11:19 | Unreached | Node should have one location but has 3. | +| ifelsestmt.c:19:6:19:18 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:19:6:19:18 | Unreached | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:29:6:29:18 | Unreached | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | AliasedDefinition | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | AliasedUse | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | Chi | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | EnterFunction | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | ExitFunction | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | InitializeNonLocal | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | ReturnVoid | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | UnmodeledDefinition | Node should have one location but has 4. | +| ifelsestmt.c:37:6:37:11 | UnmodeledUse | Node should have one location but has 4. | +| ifelsestmt.c:37:17:37:17 | VariableAddress | Node should have one location but has 2. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | VariableAddress | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | +| ifstmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| ifstmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | UnmodeledDefinition | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | UnmodeledUse | Node should have one location but has 3. | +| ifstmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | +| ifstmt.c:14:6:14:18 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | Chi | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:14:6:14:18 | Unreached | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | Chi | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:21:6:21:18 | Unreached | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | AliasedDefinition | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | AliasedUse | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | Chi | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | EnterFunction | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | ExitFunction | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | InitializeNonLocal | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | ReturnVoid | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | UnmodeledDefinition | Node should have one location but has 4. | +| ifstmt.c:27:6:27:11 | UnmodeledUse | Node should have one location but has 4. | +| ifstmt.c:27:17:27:17 | VariableAddress | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | VariableAddress | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | +| initializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| initializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| landexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| lorexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| ltrbinopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| membercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| membercallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| membercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | +| membercallexpr_args.cpp:4:14:4:14 | x | Node should have one location but has 2. | +| membercallexpr_args.cpp:4:21:4:21 | y | Node should have one location but has 2. | +| membercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition | Node should have one location but has 14. | +| membercallexpr_args.cpp:7:6:7:6 | UnmodeledUse | Node should have one location but has 14. | +| newexpr.cpp:3:9:3:9 | i | Node should have one location but has 2. | +| newexpr.cpp:3:9:3:9 | x | Node should have one location but has 2. | +| newexpr.cpp:3:16:3:16 | j | Node should have one location but has 2. | +| newexpr.cpp:3:16:3:16 | y | Node should have one location but has 2. | +| newexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| newexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| no_dynamic_init.cpp:9:5:9:8 | AliasedDefinition | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | AliasedUse | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Chi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | EnterFunction | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | ExitFunction | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | InitializeNonLocal | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | ReturnValue | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | UnmodeledUse | Node should have one location but has 4. | +| no_dynamic_init.cpp:9:5:9:8 | VariableAddress | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| nodefaultswitchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| nonmembercallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 2. | +| nonmembercallexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 2. | +| nonmembercallexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmembercallexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmemberfp2callexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| nonmemberfpcallexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| parameterinitializer.cpp:18:5:18:8 | AliasedDefinition | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | AliasedUse | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Chi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | EnterFunction | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | ExitFunction | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | InitializeNonLocal | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | ReturnValue | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | UnmodeledUse | Node should have one location but has 4. | +| parameterinitializer.cpp:18:5:18:8 | VariableAddress | Node should have one location but has 4. | +| pmcallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| pmcallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| questionexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| questionexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| revsubscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 2. | +| revsubscriptexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 2. | +| staticmembercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | UnmodeledDefinition | Node should have one location but has 14. | +| staticmembercallexpr.cpp:6:6:6:6 | UnmodeledUse | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:4:21:4:21 | x | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:4:28:4:28 | y | Node should have one location but has 2. | +| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledDefinition | Node should have one location but has 14. | +| staticmembercallexpr_args.cpp:7:6:7:6 | UnmodeledUse | Node should have one location but has 14. | +| stream_it.cpp:16:5:16:8 | AliasedDefinition | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | AliasedUse | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Chi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | EnterFunction | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | ExitFunction | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | InitializeNonLocal | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | ReturnValue | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | UnmodeledDefinition | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | UnmodeledUse | Node should have one location but has 4. | +| stream_it.cpp:16:5:16:8 | VariableAddress | Node should have one location but has 4. | +| subscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| subscriptexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| switchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| switchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | +| tinyforstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| tinyforstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | UnmodeledDefinition | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | UnmodeledUse | Node should have one location but has 20. | +| unaryopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | +| whilestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | UnmodeledDefinition | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | UnmodeledUse | Node should have one location but has 3. | +| whilestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | UnmodeledDefinition | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | UnmodeledUse | Node should have one location but has 3. | +| whilestmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | +| whilestmt.c:15:6:15:18 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | Chi | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | UnmodeledUse | Node should have one location but has 4. | +| whilestmt.c:15:6:15:18 | Unreached | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | Chi | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | UnmodeledUse | Node should have one location but has 4. | +| whilestmt.c:23:6:23:18 | Unreached | Node should have one location but has 4. | +| whilestmt.c:32:6:32:18 | AliasedDefinition | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | Chi | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | EnterFunction | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | InitializeNonLocal | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | UnmodeledDefinition | Node should have one location but has 2. | +| whilestmt.c:32:6:32:18 | Unreached | Node should have one location but has 2. | +| whilestmt.c:39:6:39:11 | AliasedDefinition | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | AliasedUse | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | Chi | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | EnterFunction | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | ExitFunction | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | InitializeNonLocal | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | ReturnVoid | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | UnmodeledDefinition | Node should have one location but has 4. | +| whilestmt.c:39:6:39:11 | UnmodeledUse | Node should have one location but has 4. | +missingLocation +| Nodes without location: 30 | +uniqueNodeToString +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | +| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | +| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | +| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:9:3:9 | i | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:9:3:9 | x | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:16:3:16 | j | Node should have one toString but has 2. | +| constructorinitializer.cpp:3:16:3:16 | y | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | +| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | +| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | +| ir.cpp:888:6:888:16 | (no string representation) | Node should have one toString but has 0. | +| misc.c:197:6:197:9 | (no string representation) | Node should have one toString but has 0. | +| newexpr.cpp:3:9:3:9 | i | Node should have one toString but has 2. | +| newexpr.cpp:3:9:3:9 | x | Node should have one toString but has 2. | +| newexpr.cpp:3:16:3:16 | j | Node should have one toString but has 2. | +| newexpr.cpp:3:16:3:16 | y | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | +| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | +missingToString +| Nodes without toString: 2 | +parameterCallable +localFlowIsLocal +compatibleTypesReflexive +unreachableNodeCCtx +localCallNodes +postIsNotPre +postHasUniquePre +uniquePostUpdate +postIsInSameCallable +reverseRead +storeIsPostUpdate +argHasPostUpdate diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql new file mode 100644 index 00000000000..6d9f8e314f7 --- /dev/null +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.ql @@ -0,0 +1 @@ +import semmle.code.cpp.ir.dataflow.internal.DataFlowImplConsistency::Consistency diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 02a088752dd..3b748cc8ed2 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -49,6 +49,7 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| CPP-309.cpp:7:5:7:20 | InitializeDynamicAllocation: new[] | | VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | @@ -57,7 +58,9 @@ instructionWithoutSuccessor | condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | +| cpp17.cpp:15:5:15:45 | InitializeDynamicAllocation: new | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | +| enum.c:6:9:6:9 | Constant: (int)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | @@ -138,50 +141,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -268,50 +269,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -416,50 +415,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -518,50 +515,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | @@ -594,6 +589,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 82b5f5ccef0..5f7a2523610 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -30,7 +30,6 @@ missingOperand unexpectedOperand duplicateOperand missingPhiOperand -| cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | | range_analysis.c:373:3:373:47 | Phi: return ... | range_analysis.c:371:37:371:39 | Constant: 500 | @@ -92,50 +91,48 @@ ambiguousSuccessors | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | pmcallexpr.cpp:7:5:7:5 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | assignexpr.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | staticmembercallexpr_args.cpp:8:6:8:6 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| break_labels.c:2:11:2:11 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | conditional_destructors.cpp:30:9:30:13 | FunctionAddress: call to C1 | | conditional_destructors.cpp:29:6:29:7 | UnmodeledDefinition: f1 | Goto | 2 | forstmt.cpp:2:14:2:14 | VariableAddress: definition of i | | conditional_destructors.cpp:38:6:38:7 | UnmodeledDefinition: f2 | Goto | 2 | conditional_destructors.cpp:39:9:39:13 | FunctionAddress: call to C2 | @@ -222,50 +219,48 @@ ambiguousSuccessors | dostmt.c:16:6:16:18 | UnmodeledDefinition: always_true_2 | Goto | 4 | whilestmt.c:24:9:24:9 | Constant: 1 | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | dostmt.c:27:5:27:7 | NoOp: label ...: | | dostmt.c:25:6:25:18 | UnmodeledDefinition: always_true_3 | Goto | 2 | whilestmt.c:33:9:33:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| duff.c:2:12:2:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | array_delete.cpp:6:12:6:24 | Constant: (Foo *)... | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | assignexpr.cpp:7:4:7:4 | VariableAddress: definition of c | | fieldaccess.cpp:6:6:6:6 | UnmodeledDefinition: f | Goto | 14 | constmemberaccess.cpp:7:5:7:5 | VariableAddress: definition of c | @@ -370,50 +365,48 @@ ambiguousSuccessors | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | no_dynamic_init.cpp:9:5:9:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | nonmembercallexpr.c:1:12:1:12 | NoOp: return ... | | nonmembercallexpr.c:1:6:1:6 | UnmodeledDefinition: g | Goto | 2 | revsubscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | | parameterinitializer.cpp:18:5:18:8 | UnmodeledDefinition: main | Goto | 4 | allocators.cpp:16:8:16:10 | VariableAddress: definition of foo | @@ -472,50 +465,48 @@ ambiguousSuccessors | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | no_dynamic_init.cpp:11:3:11:11 | VariableAddress: return ... | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | parameterinitializer.cpp:19:5:19:5 | FunctionAddress: call to f | | stream_it.cpp:16:5:16:8 | UnmodeledDefinition: main | Goto | 4 | stream_it.cpp:18:15:18:16 | VariableAddress: definition of xs | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | duff.c:3:9:3:9 | VariableAddress: definition of n | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | dummyblock.c:2:9:2:9 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | emptyblock.c:2:5:3:5 | NoOp: { ... } | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | enum.c:6:2:6:10 | VariableAddress: return ... | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | exprstmt.c:2:5:2:5 | Constant: 1 | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | initializer.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: i | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | switchstmt.c:2:14:2:14 | VariableAddress: x | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | tinyforstmt.c:3:9:3:9 | NoOp: ; | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 20 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: i | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | aggregateinitializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | break_labels.c:3:9:3:14 | VariableAddress: definition of result | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | duff.c:3:9:3:9 | VariableAddress: definition of n | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | dummyblock.c:2:9:2:9 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | emptyblock.c:2:5:3:5 | NoOp: { ... } | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | exprstmt.c:2:5:2:5 | Constant: 1 | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | initializer.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | landexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | lorexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | ltrbinopexpr.c:2:9:2:9 | VariableAddress: definition of i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nodefaultswitchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmembercallexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfp2callexpr.c:4:2:4:2 | FunctionAddress: call to g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | nonmemberfpcallexpr.c:2:8:2:8 | VariableAddress: definition of g | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | questionexpr.c:2:6:2:6 | VariableAddress: definition of a | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | subscriptexpr.c:2:9:2:9 | VariableAddress: definition of x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: i | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | switchstmt.c:2:14:2:14 | VariableAddress: x | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | tinyforstmt.c:3:9:3:9 | NoOp: ; | +| switchstmt.c:1:12:1:12 | InitializeParameter: x | Goto | 19 | unaryopexpr.c:2:9:2:9 | VariableAddress: definition of i | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifelsestmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | ifstmt.c:2:6:2:6 | Constant: 0 | | whilestmt.c:1:6:1:19 | UnmodeledDefinition: always_false_1 | Goto | 3 | whilestmt.c:2:9:2:9 | Constant: 0 | @@ -548,6 +539,7 @@ unexplainedLoop | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | Load: x | | range_analysis.c:355:14:355:27 | test_ternary01 | range_analysis.c:367:10:367:10 | VariableAddress: x | unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql index c9cccbf24ae..be844bcf185 100644 --- a/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql +++ b/cpp/ql/test/library-tests/templates/prototype_bodies/isdef_hasblock.ql @@ -3,6 +3,6 @@ import cpp // It should be the case that "f.isDefined()" is equivalent to "exists(f.getBlock())". from Function f, string isdef, string hasblock where - (if f.isDefined() then isdef = "defined" else isdef = "not defined") and + (if f.hasDefinition() then isdef = "defined" else isdef = "not defined") and (if exists(f.getBlock()) then hasblock = "has block" else hasblock = "no block") select f.getName(), isdef, hasblock diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index a492fb47d41..54982a6bc37 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -1,80 +1,78 @@ test.cpp: -# 1| int test00(int, int) +# 1| void test00(int, int) # 1| Block 0 -# 1| v1_1(void) = EnterFunction : -# 1| m1_2(unknown) = AliasedDefinition : +# 1| v1_1(void) = EnterFunction : +# 1| m1_2(unknown) = AliasedDefinition : # 1| valnum = unique -# 1| m1_3(unknown) = InitializeNonLocal : +# 1| m1_3(unknown) = InitializeNonLocal : # 1| valnum = unique -# 1| m1_4(unknown) = Chi : total:m1_2, partial:m1_3 +# 1| m1_4(unknown) = Chi : total:m1_2, partial:m1_3 # 1| valnum = unique -# 1| mu1_5(unknown) = UnmodeledDefinition : +# 1| mu1_5(unknown) = UnmodeledDefinition : # 1| valnum = unique -# 1| r1_6(glval) = VariableAddress[p0] : +# 1| r1_6(glval) = VariableAddress[p0] : # 1| valnum = r1_6, r5_1, r6_1 -# 1| m1_7(int) = InitializeParameter[p0] : &:r1_6 +# 1| m1_7(int) = InitializeParameter[p0] : &:r1_6 # 1| valnum = m1_7, r5_2, r6_2 -# 1| r1_8(glval) = VariableAddress[p1] : +# 1| r1_8(glval) = VariableAddress[p1] : # 1| valnum = r1_8, r5_3, r6_3 -# 1| m1_9(int) = InitializeParameter[p1] : &:r1_8 +# 1| m1_9(int) = InitializeParameter[p1] : &:r1_8 # 1| valnum = m1_9, r5_4, r6_4 -# 2| r2_1(glval) = VariableAddress[x] : +# 2| r2_1(glval) = VariableAddress[x] : # 2| valnum = r2_1, r5_6, r6_6, r7_1 -# 2| m2_2(int) = Uninitialized[x] : &:r2_1 +# 2| m2_2(int) = Uninitialized[x] : &:r2_1 # 2| valnum = unique -# 2| r2_3(glval) = VariableAddress[y] : +# 2| r2_3(glval) = VariableAddress[y] : # 2| valnum = r2_3, r7_3 -# 2| m2_4(int) = Uninitialized[y] : &:r2_3 +# 2| m2_4(int) = Uninitialized[y] : &:r2_3 # 2| valnum = unique -# 3| r3_1(glval) = VariableAddress[b] : +# 3| r3_1(glval) = VariableAddress[b] : # 3| valnum = unique -# 3| m3_2(unsigned char) = Uninitialized[b] : &:r3_1 +# 3| m3_2(unsigned char) = Uninitialized[b] : &:r3_1 # 3| valnum = unique -# 5| r5_1(glval) = VariableAddress[p0] : +# 5| r5_1(glval) = VariableAddress[p0] : # 5| valnum = r1_6, r5_1, r6_1 -# 5| r5_2(int) = Load : &:r5_1, m1_7 +# 5| r5_2(int) = Load : &:r5_1, m1_7 # 5| valnum = m1_7, r5_2, r6_2 -# 5| r5_3(glval) = VariableAddress[p1] : +# 5| r5_3(glval) = VariableAddress[p1] : # 5| valnum = r1_8, r5_3, r6_3 -# 5| r5_4(int) = Load : &:r5_3, m1_9 +# 5| r5_4(int) = Load : &:r5_3, m1_9 # 5| valnum = m1_9, r5_4, r6_4 -# 5| r5_5(int) = Add : r5_2, r5_4 +# 5| r5_5(int) = Add : r5_2, r5_4 # 5| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 5| r5_6(glval) = VariableAddress[x] : +# 5| r5_6(glval) = VariableAddress[x] : # 5| valnum = r2_1, r5_6, r6_6, r7_1 -# 5| m5_7(int) = Store : &:r5_6, r5_5 +# 5| m5_7(int) = Store : &:r5_6, r5_5 # 5| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 6| r6_1(glval) = VariableAddress[p0] : +# 6| r6_1(glval) = VariableAddress[p0] : # 6| valnum = r1_6, r5_1, r6_1 -# 6| r6_2(int) = Load : &:r6_1, m1_7 +# 6| r6_2(int) = Load : &:r6_1, m1_7 # 6| valnum = m1_7, r5_2, r6_2 -# 6| r6_3(glval) = VariableAddress[p1] : +# 6| r6_3(glval) = VariableAddress[p1] : # 6| valnum = r1_8, r5_3, r6_3 -# 6| r6_4(int) = Load : &:r6_3, m1_9 +# 6| r6_4(int) = Load : &:r6_3, m1_9 # 6| valnum = m1_9, r5_4, r6_4 -# 6| r6_5(int) = Add : r6_2, r6_4 +# 6| r6_5(int) = Add : r6_2, r6_4 # 6| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 6| r6_6(glval) = VariableAddress[x] : +# 6| r6_6(glval) = VariableAddress[x] : # 6| valnum = r2_1, r5_6, r6_6, r7_1 -# 6| m6_7(int) = Store : &:r6_6, r6_5 +# 6| m6_7(int) = Store : &:r6_6, r6_5 # 6| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 7| r7_1(glval) = VariableAddress[x] : +# 7| r7_1(glval) = VariableAddress[x] : # 7| valnum = r2_1, r5_6, r6_6, r7_1 -# 7| r7_2(int) = Load : &:r7_1, m6_7 +# 7| r7_2(int) = Load : &:r7_1, m6_7 # 7| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_3(glval) = VariableAddress[y] : # 7| valnum = r2_3, r7_3 -# 7| m7_4(int) = Store : &:r7_3, r7_2 +# 7| m7_4(int) = Store : &:r7_3, r7_2 # 7| valnum = m5_7, m6_7, m7_4, r5_5, r6_5, r7_2 -# 8| v8_1(void) = NoOp : -# 1| r1_10(glval) = VariableAddress[#return] : -# 1| valnum = unique -# 1| v1_11(void) = ReturnValue : &:r1_10 -# 1| v1_12(void) = UnmodeledUse : mu* -# 1| v1_13(void) = AliasedUse : m1_3 -# 1| v1_14(void) = ExitFunction : +# 8| v8_1(void) = NoOp : +# 1| v1_10(void) = ReturnVoid : +# 1| v1_11(void) = UnmodeledUse : mu* +# 1| v1_12(void) = AliasedUse : m1_3 +# 1| v1_13(void) = ExitFunction : -# 12| int test01(int, int) +# 12| void test01(int, int) # 12| Block 0 # 12| v12_1(void) = EnterFunction : # 12| m12_2(unknown) = AliasedDefinition : @@ -154,14 +152,12 @@ test.cpp: # 18| m18_4(int) = Store : &:r18_3, r18_2 # 18| valnum = m16_10, m17_10, m18_4, r16_8, r17_8, r18_2 # 19| v19_1(void) = NoOp : -# 12| r12_10(glval) = VariableAddress[#return] : -# 12| valnum = unique -# 12| v12_11(void) = ReturnValue : &:r12_10 -# 12| v12_12(void) = UnmodeledUse : mu* -# 12| v12_13(void) = AliasedUse : m12_3 -# 12| v12_14(void) = ExitFunction : +# 12| v12_10(void) = ReturnVoid : +# 12| v12_11(void) = UnmodeledUse : mu* +# 12| v12_12(void) = AliasedUse : m12_3 +# 12| v12_13(void) = ExitFunction : -# 25| int test02(int, int) +# 25| void test02(int, int) # 25| Block 0 # 25| v25_1(void) = EnterFunction : # 25| m25_2(unknown) = AliasedDefinition : @@ -248,14 +244,12 @@ test.cpp: # 32| m32_4(int) = Store : &:r32_3, r32_2 # 32| valnum = m31_10, m32_4, r31_8, r32_2 # 33| v33_1(void) = NoOp : -# 25| r25_10(glval) = VariableAddress[#return] : -# 25| valnum = unique -# 25| v25_11(void) = ReturnValue : &:r25_10 -# 25| v25_12(void) = UnmodeledUse : mu* -# 25| v25_13(void) = AliasedUse : ~m30_4 -# 25| v25_14(void) = ExitFunction : +# 25| v25_10(void) = ReturnVoid : +# 25| v25_11(void) = UnmodeledUse : mu* +# 25| v25_12(void) = AliasedUse : ~m30_4 +# 25| v25_13(void) = ExitFunction : -# 39| int test03(int, int, int*) +# 39| void test03(int, int, int*) # 39| Block 0 # 39| v39_1(void) = EnterFunction : # 39| m39_2(unknown) = AliasedDefinition : @@ -355,13 +349,11 @@ test.cpp: # 46| m46_4(int) = Store : &:r46_3, r46_2 # 46| valnum = m43_10, m45_10, m46_4, r43_8, r45_8, r46_2 # 47| v47_1(void) = NoOp : -# 39| v39_14(void) = ReturnIndirection : &:r39_12, m44_6 -# 39| r39_15(glval) = VariableAddress[#return] : -# 39| valnum = unique -# 39| v39_16(void) = ReturnValue : &:r39_15 -# 39| v39_17(void) = UnmodeledUse : mu* -# 39| v39_18(void) = AliasedUse : m39_3 -# 39| v39_19(void) = ExitFunction : +# 39| v39_14(void) = ReturnIndirection[p2] : &:r39_12, m44_6 +# 39| v39_15(void) = ReturnVoid : +# 39| v39_16(void) = UnmodeledUse : mu* +# 39| v39_17(void) = AliasedUse : m39_3 +# 39| v39_18(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -433,27 +425,27 @@ test.cpp: #-----| Goto -> Block 3 # 56| Block 3 -# 56| m56_1(decltype(nullptr)) = Phi : from 2:m55_4, from 5:m56_23 +# 56| m56_1(char *) = Phi : from 2:m55_4, from 5:m56_23 # 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2 -# 56| r56_2(glval) = VariableAddress[ptr] : +# 56| r56_2(glval) = VariableAddress[ptr] : # 56| valnum = r50_1, r55_3, r56_12, r56_19, r56_2, r59_1 -# 56| r56_3(char *) = Load : &:r56_2, m56_1 +# 56| r56_3(char *) = Load : &:r56_2, m56_1 # 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2 -# 56| r56_4(char) = Load : &:r56_3, ~m49_4 +# 56| r56_4(char) = Load : &:r56_3, ~m49_4 # 56| valnum = r56_14, r56_4, r59_3 -# 56| r56_5(int) = Convert : r56_4 +# 56| r56_5(int) = Convert : r56_4 # 56| valnum = r56_15, r56_5, r59_4 -# 56| r56_6(glval) = VariableAddress[str] : +# 56| r56_6(glval) = VariableAddress[str] : # 56| valnum = r49_6, r53_2, r56_6 -# 56| r56_7(char *) = Load : &:r56_6, m49_7 +# 56| r56_7(char *) = Load : &:r56_6, m49_7 # 56| valnum = m49_7, r49_8, r53_3, r56_7 -# 56| r56_8(char) = Load : &:r56_7, ~m49_9 +# 56| r56_8(char) = Load : &:r56_7, ~m49_9 # 56| valnum = r53_4, r56_8 -# 56| r56_9(int) = Convert : r56_8 +# 56| r56_9(int) = Convert : r56_8 # 56| valnum = r53_5, r56_9 -# 56| r56_10(bool) = CompareNE : r56_5, r56_9 +# 56| r56_10(bool) = CompareNE : r56_5, r56_9 # 56| valnum = unique -# 56| v56_11(void) = ConditionalBranch : r56_10 +# 56| v56_11(void) = ConditionalBranch : r56_10 #-----| False -> Block 6 #-----| True -> Block 4 @@ -531,8 +523,8 @@ test.cpp: # 65| valnum = m53_1, m65_4, r62_2, r65_3 # 65| m65_4(unsigned int) = Store : &:r65_1, r65_3 # 65| valnum = m53_1, m65_4, r62_2, r65_3 -# 49| v49_14(void) = ReturnIndirection : &:r49_8, m49_9 -# 49| v49_15(void) = ReturnIndirection : &:r49_12, m49_13 +# 49| v49_14(void) = ReturnIndirection[str] : &:r49_8, m49_9 +# 49| v49_15(void) = ReturnIndirection[chars] : &:r49_12, m49_13 # 49| r49_16(glval) = VariableAddress[#return] : # 49| valnum = r49_16, r65_1 # 49| v49_17(void) = ReturnValue : &:r49_16, m65_4 @@ -625,14 +617,14 @@ test.cpp: #-----| Goto -> Block 2 # 82| Block 2 -# 82| m82_1(unknown) = Phi : from 0:~m77_5, from 1:~m80_4 +# 82| m82_1(unknown) = Phi : from 0:~m77_5, from 1:~m80_4 # 82| valnum = unique -# 82| v82_2(void) = NoOp : -# 75| v75_10(void) = ReturnIndirection : &:r75_8, m75_9 -# 75| v75_11(void) = ReturnVoid : -# 75| v75_12(void) = UnmodeledUse : mu* -# 75| v75_13(void) = AliasedUse : ~m82_1 -# 75| v75_14(void) = ExitFunction : +# 82| v82_2(void) = NoOp : +# 75| v75_10(void) = ReturnIndirection[vals] : &:r75_8, m75_9 +# 75| v75_11(void) = ReturnVoid : +# 75| v75_12(void) = UnmodeledUse : mu* +# 75| v75_13(void) = AliasedUse : ~m82_1 +# 75| v75_14(void) = ExitFunction : # 84| void test05(int, int, void*) # 84| Block 0 @@ -689,7 +681,7 @@ test.cpp: # 88| m88_10(int) = Store : &:r88_9, r88_8 # 88| valnum = m88_10, m88_6, r88_8 # 89| v89_1(void) = NoOp : -# 84| v84_14(void) = ReturnIndirection : &:r84_12, m84_13 +# 84| v84_14(void) = ReturnIndirection[p] : &:r84_12, m84_13 # 84| v84_15(void) = ReturnVoid : # 84| v84_16(void) = UnmodeledUse : mu* # 84| v84_17(void) = AliasedUse : m84_3 @@ -818,7 +810,7 @@ test.cpp: # 109| valnum = m105_7, m107_6, m109_4, r105_6, r107_5, r109_3 # 109| m109_4(int) = Store : &:r109_1, r109_3 # 109| valnum = m105_7, m107_6, m109_4, r105_6, r107_5, r109_3 -# 104| v104_10(void) = ReturnIndirection : &:r104_8, m104_9 +# 104| v104_10(void) = ReturnIndirection[pd] : &:r104_8, m104_9 # 104| r104_11(glval) = VariableAddress[#return] : # 104| valnum = r104_11, r109_1 # 104| v104_12(void) = ReturnValue : &:r104_11, m109_4 @@ -925,7 +917,7 @@ test.cpp: # 129| m129_6(int) = Store : &:r129_1, r129_5 # 129| valnum = m124_11, m128_6, m129_6, r128_2, r129_5 # 130| v130_1(void) = NoOp : -# 124| v124_12(void) = ReturnIndirection : &:r124_8, m128_7 +# 124| v124_12(void) = ReturnIndirection[pa] : &:r124_8, m128_7 # 124| v124_13(void) = ReturnVoid : # 124| v124_14(void) = UnmodeledUse : mu* # 124| v124_15(void) = AliasedUse : m124_3 @@ -1068,7 +1060,7 @@ test.cpp: # 149| m149_6(int) = Store : &:r149_1, r149_5 # 149| valnum = m144_6, m149_6, r144_5, r149_5 # 150| v150_1(void) = NoOp : -# 143| v143_10(void) = ReturnIndirection : &:r143_8, m147_7 +# 143| v143_10(void) = ReturnIndirection[pa] : &:r143_8, m147_7 # 143| v143_11(void) = ReturnVoid : # 143| v143_12(void) = UnmodeledUse : mu* # 143| v143_13(void) = AliasedUse : m143_3 diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql index 528bb6174a5..3debea869b4 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.ql @@ -5,3 +5,4 @@ import semmle.code.cpp.ir.PrintIR import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.ValueNumbering +import semmle.code.cpp.ir.implementation.aliased_ssa.gvn.PrintValueNumbering diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp index 3e878ac2356..dfef91006e3 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp @@ -1,4 +1,4 @@ -int test00(int p0, int p1) { +void test00(int p0, int p1) { int x, y; unsigned char b; @@ -9,7 +9,7 @@ int test00(int p0, int p1) { int global01 = 1; -int test01(int p0, int p1) { +void test01(int p0, int p1) { int x, y; unsigned char b; @@ -22,7 +22,7 @@ int global02 = 2; void change_global02(); // Just a declaration -int test02(int p0, int p1) { +void test02(int p0, int p1) { int x, y; unsigned char b; @@ -36,7 +36,7 @@ int global03 = 3; void change_global03(); // Just a declaration -int test03(int p0, int p1, int* p2) { +void test03(int p0, int p1, int* p2) { int x, y; unsigned char b; diff --git a/cpp/ql/test/library-tests/variables/variables/types.expected b/cpp/ql/test/library-tests/variables/variables/types.expected index cdc8c42a762..9f5df340263 100644 --- a/cpp/ql/test/library-tests/variables/variables/types.expected +++ b/cpp/ql/test/library-tests/variables/variables/types.expected @@ -1,21 +1,21 @@ | ..()(..) | RoutineType | | | | | | ..(*)(..) | FunctionPointerType | | ..()(..) | | | -| _Complex __float128 | FloatingPointType | | | | | -| _Complex double | FloatingPointType | | | | | -| _Complex float | FloatingPointType | | | | | -| _Complex long double | FloatingPointType | | | | | +| _Complex __float128 | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex double | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex float | BinaryFloatingPointType, ComplexNumberType | | | | | +| _Complex long double | BinaryFloatingPointType, ComplexNumberType | | | | | | _Decimal32 | Decimal32Type | | | | | | _Decimal64 | Decimal64Type | | | | | | _Decimal128 | Decimal128Type | | | | | -| _Float32 | FloatingPointType | | | | | -| _Float32x | FloatingPointType | | | | | -| _Float64 | FloatingPointType | | | | | -| _Float64x | FloatingPointType | | | | | -| _Float128 | FloatingPointType | | | | | -| _Float128x | FloatingPointType | | | | | -| _Imaginary double | FloatingPointType | | | | | -| _Imaginary float | FloatingPointType | | | | | -| _Imaginary long double | FloatingPointType | | | | | +| _Float32 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float32x | BinaryFloatingPointType, RealNumberType | | | | | +| _Float64 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float64x | BinaryFloatingPointType, RealNumberType | | | | | +| _Float128 | BinaryFloatingPointType, RealNumberType | | | | | +| _Float128x | BinaryFloatingPointType, RealNumberType | | | | | +| _Imaginary double | BinaryFloatingPointType, ImaginaryNumberType | | | | | +| _Imaginary float | BinaryFloatingPointType, ImaginaryNumberType | | | | | +| _Imaginary long double | BinaryFloatingPointType, ImaginaryNumberType | | | | | | __float128 | Float128Type | | | | | | __int128 | Int128Type | | | | | | __va_list_tag | DirectAccessHolder, MetricClass, Struct, StructLikeClass | | | | | diff --git a/cpp/ql/test/qlpack.yml b/cpp/ql/test/qlpack.yml index 36dcb70d4ef..008af57baef 100644 --- a/cpp/ql/test/qlpack.yml +++ b/cpp/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-cpp-tests version: 0.0.0 libraryPathDependencies: codeql-cpp +extractor: cpp diff --git a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected index 7350749ce96..45f88d426c9 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected +++ b/cpp/ql/test/query-tests/Critical/NewFree/NewFreeMismatch.expected @@ -1,5 +1,9 @@ | test2.cpp:19:3:19:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:18:12:18:18 | new | new | | test2.cpp:26:3:26:6 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:25:7:25:13 | new | new | +| test2.cpp:51:2:51:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:45:18:45:24 | new | new | +| test2.cpp:55:2:55:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test2.cpp:46:20:46:33 | call to operator new | new | +| test2.cpp:57:2:57:18 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | +| test2.cpp:58:2:58:18 | call to operator delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test2.cpp:47:21:47:26 | call to malloc | malloc | | test.cpp:36:2:36:17 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:27:18:27:23 | call to malloc | malloc | | test.cpp:41:2:41:5 | call to free | There is a new/free mismatch between this free and the corresponding $@. | test.cpp:26:7:26:17 | new | new | | test.cpp:68:3:68:11 | delete | There is a malloc/delete mismatch between this delete and the corresponding $@. | test.cpp:64:28:64:33 | call to malloc | malloc | diff --git a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp index 9101758d85b..43a286f6f97 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp +++ b/cpp/ql/test/query-tests/Critical/NewFree/test2.cpp @@ -34,3 +34,27 @@ public: }; MyTest2Class mt2c_i; + +// --- + +void* operator new(size_t); +void operator delete(void*); + +void test_operator_new() +{ + void *ptr_new = new int; + void *ptr_opnew = ::operator new(sizeof(int)); + void *ptr_malloc = malloc(sizeof(int)); + + delete ptr_new; // GOOD + ::operator delete(ptr_new); // GOOD + free(ptr_new); // BAD + + delete ptr_opnew; // GOOD + ::operator delete(ptr_opnew); // GOOD + free(ptr_opnew); // BAD + + delete ptr_malloc; // BAD + ::operator delete(ptr_malloc); // BAD + free(ptr_malloc); // GOOD +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 7a58fb1b608..d7db531fbde 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -1 +1,13 @@ -| test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename) | test.c:9:23:9:26 | argv | user input (argv) | +edges +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | (const char *)... | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | (const char *)... | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | +| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | +nodes +| test.c:9:23:9:26 | argv | semmle.label | argv | +| test.c:9:23:9:26 | argv | semmle.label | argv | +| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | +| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | +| test.c:17:11:17:18 | fileName | semmle.label | fileName | +#select +| test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename) | test.c:9:23:9:26 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index bfdbb13a097..17bb67fdc08 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -1,2 +1,30 @@ -| search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | -| search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | +edges +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | (const char *)... | +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | 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 | +| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:45:17:45:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | +| search.c:41:21:41:26 | call to getenv | search.c:47:17:47:25 | raw_query | +| search.c:45:17:45:25 | raw_query | search.c:14:24:14:28 | query | +| search.c:47:17:47:25 | raw_query | search.c:22:24:22:28 | query | +nodes +| search.c:14:24:14:28 | query | semmle.label | query | +| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | +| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:17:8:17:12 | query | semmle.label | query | +| search.c:22:24:22:28 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:23:39:23:43 | query | semmle.label | query | +| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | +| search.c:41:21:41:26 | call to getenv | semmle.label | call to getenv | +| search.c:45:17:45:25 | raw_query | semmle.label | raw_query | +| search.c:47:17:47:25 | raw_query | semmle.label | raw_query | +#select +| search.c:17:8:17:12 | query | search.c:41:21:41:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | +| search.c:23:39:23:43 | query | search.c:41:21:41:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:41:21:41:26 | call to getenv | this query data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index b494196d4aa..f84c6719157 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -1,2 +1,25 @@ -| 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 | 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 | +edges +| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command | +| test.cpp:24:30:24:36 | command | test.cpp:26:10:26: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 | +| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command | +| test.cpp:42:18:42:34 | (const char *)... | test.cpp:24:30:24:36 | command | +| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command | +| test.cpp:43:18:43:34 | (const char *)... | test.cpp:29:30:29:36 | command | +nodes +| test.cpp:24:30:24:36 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:26:10:26:16 | command | semmle.label | command | +| test.cpp:29:30:29:36 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| test.cpp:31:10:31:16 | command | semmle.label | command | +| 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:43:18:43:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... | +#select +| 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 | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected index e69de29bb2d..58e3dda0964 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/UnboundedWrite.expected @@ -0,0 +1,3 @@ +edges +nodes +#select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected index 5096e75ebc3..291c1cb3a71 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected @@ -1,5 +1,53 @@ -| tests.c:28:3:28:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | -| tests.c:29:3:29:9 | call to sprintf | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | -| tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | -| tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 | -| tests.c:34:25:34:33 | buffer100 | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv | +edges +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +nodes +| tests.c:28:22:28:25 | argv | semmle.label | argv | +| tests.c:28:22:28:25 | argv | semmle.label | argv | +| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | +| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | +| tests.c:29:28:29:31 | argv | semmle.label | argv | +| tests.c:29:28:29:31 | argv | semmle.label | argv | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:29:28:29:34 | access to array | semmle.label | access to array | +| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | +| tests.c:34:10:34:13 | argv | semmle.label | argv | +| tests.c:34:10:34:13 | argv | semmle.label | argv | +| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | +| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | +#select +| tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | +| tests.c:29:3:29:9 | call to sprintf | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | +| tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | tests.c:31:15:31:23 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:31:15:31:23 | buffer100 | buffer100 | +| tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | tests.c:33:21:33:29 | buffer100 | This 'scanf string argument' with input from $@ may overflow the destination. | tests.c:33:21:33:29 | buffer100 | buffer100 | +| tests.c:34:25:34:33 | buffer100 | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | This 'sscanf string argument' with input from $@ may overflow the destination. | tests.c:34:10:34:13 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 7f342b0aabe..0064b6d5715 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -1,28 +1,314 @@ -| argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:95:9:95:12 | argv | argv | -| argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:96:15:96:18 | argv | argv | -| argvLocal.c:101:9:101:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:102:15:102:16 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:106:9:106:13 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:107:15:107:19 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:110:9:110:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:111:15:111:17 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | -| argvLocal.c:116:9:116:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:117:15:117:16 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:121:9:121:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:122:15:122:16 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:127:9:127:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:128:15:128:16 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:131:9:131:14 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | -| argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | -| argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | -| argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:149:11:149:14 | argv | argv | -| argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:149:11:149:14 | argv | argv | -| argvLocal.c:157:9:157:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:158:15:158:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:164:9:164:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:163:22:163:25 | argv | argv | -| argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:163:22:163:25 | argv | argv | -| argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:168:18:168:21 | argv | argv | -| argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:168:18:168:21 | argv | argv | +edges +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | +| 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: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 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | 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: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:117:15:117:16 | array to pointer conversion | 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:122:15:122:16 | i4 | +| 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 | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:122:15:122:16 | printWrapper output argument | +| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | +| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:128:15:128:16 | array to pointer conversion | argvLocal.c:128:15:128:16 | printWrapper output argument | +| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | (const char *)... | +| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | +nodes +| argvLocal.c:9:25:9:31 | correct | semmle.label | correct | +| argvLocal.c:10:9:10:15 | Chi | semmle.label | Chi | +| argvLocal.c:95:9:95:12 | argv | semmle.label | argv | +| argvLocal.c:95:9:95:12 | argv | semmle.label | argv | +| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:18 | argv | semmle.label | argv | +| argvLocal.c:96:15:96:18 | argv | semmle.label | argv | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | +| argvLocal.c:100:7:100:10 | argv | semmle.label | argv | +| argvLocal.c:100:7:100:10 | argv | semmle.label | argv | +| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | +| argvLocal.c:105:14:105:17 | argv | semmle.label | argv | +| argvLocal.c:105:14:105:17 | argv | semmle.label | argv | +| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | +| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | +| argvLocal.c:115:13:115:16 | argv | semmle.label | argv | +| argvLocal.c:115:13:115:16 | argv | semmle.label | argv | +| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | +| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 | +| argvLocal.c:117:15:117:16 | printWrapper output argument | semmle.label | printWrapper output argument | +| 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:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | +| argvLocal.c:122:15:122:16 | printWrapper output argument | semmle.label | printWrapper output argument | +| argvLocal.c:126:10:126:13 | argv | semmle.label | argv | +| argvLocal.c:126:10:126:13 | argv | semmle.label | argv | +| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | +| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 | +| argvLocal.c:128:15:128:16 | printWrapper output argument | semmle.label | printWrapper output argument | +| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | +| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | +| argvLocal.c:149:11:149:14 | argv | semmle.label | argv | +| argvLocal.c:149:11:149:14 | argv | semmle.label | argv | +| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | +| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | +| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | +| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | +| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | +| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | +| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | +| argvLocal.c:168:18:168:21 | argv | semmle.label | argv | +| argvLocal.c:168:18:168:21 | argv | semmle.label | argv | +| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | +#select +| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:95:9:95:12 | argv | argv | +| argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:96:15:96:18 | argv | argv | +| argvLocal.c:101:9:101:10 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:102:15:102:16 | i1 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:107:15:107:19 | access to array | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:111:15:111:17 | * ... | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:105:14:105:17 | argv | argv | +| argvLocal.c:116:9:116:10 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:117:15:117:16 | i3 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:121:9:121:10 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:122:15:122:16 | i4 | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:127:9:127:10 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:128:15:128:16 | i5 | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:131:9:131:14 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:132:15:132:20 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:135:9:135:12 | ... ++ | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:136:15:136:18 | -- ... | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:144:9:144:10 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:145:15:145:16 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:100:7:100:10 | argv | argv | +| argvLocal.c:150:9:150:10 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:149:11:149:14 | argv | argv | +| argvLocal.c:151:15:151:16 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:149:11:149:14 | argv | argv | +| argvLocal.c:157:9:157:10 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:156:23:156:26 | argv | argv | +| argvLocal.c:158:15:158:16 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:156:23:156:26 | argv | argv | +| argvLocal.c:164:9:164:11 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:163:22:163:25 | argv | argv | +| argvLocal.c:165:15:165:17 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:163:22:163:25 | argv | argv | +| argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | argvLocal.c:168:18:168:21 | argv | argv | +| argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format) | argvLocal.c:168:18:168:21 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 2417990beb2..a05e392ecf2 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -1,7 +1,83 @@ -| funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | -| funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | -| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | -| funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | -| funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | -| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | -| funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | +edges +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | +| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | (const char *)... | +| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | +nodes +| funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument | +| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | +| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | +| funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument | +| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | +| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | +| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | +| funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | +| funcsLocal.c:31:19:31:21 | fgets output argument | semmle.label | fgets output argument | +| funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 | +| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | +| funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument | +| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | +| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | +| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | +| funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | +| funcsLocal.c:41:18:41:20 | gets output argument | semmle.label | gets output argument | +| funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 | +| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | +| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | +#select +| funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | +| funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:26:8:26:9 | i3 | fgets | +| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:13:31:17 | call to fgets | fgets | +| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:31:19:31:21 | i41 | fgets | +| funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:36:7:36:8 | i5 | gets | +| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:13:41:16 | call to gets | gets | +| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:41:18:41:20 | i61 | gets | +| funcsLocal.c:58:9:58:10 | e1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | funcsLocal.c:16:8:16:9 | i1 | fread | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected index e69de29bb2d..58e3dda0964 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected @@ -0,0 +1,3 @@ +edges +nodes +#select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 0f29313da8e..ba735a3e140 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -1,5 +1,65 @@ -| globalVars.c:27:9:27:12 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:30:15:30:18 | copy | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:8:7:8:10 | copy | copy | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:38:9:38:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:41:15:41:19 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | -| globalVars.c:50:9:50:13 | copy2 | This value may flow through $@, originating from $@, and is a formatting argument to printf(format). | globalVars.c:9:7:9:11 | copy2 | copy2 | globalVars.c:24:11:24:14 | argv | argv | +edges +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | +| globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | +| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store | +| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy | +| 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:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | +| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | +| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... | +| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy | +| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val | +| 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:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | +| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 | +nodes +| globalVars.c:8:7:8:10 | copy | semmle.label | copy | +| globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 | +| globalVars.c:11:22:11:25 | argv | semmle.label | argv | +| globalVars.c:12:2:12:15 | Store | semmle.label | Store | +| globalVars.c:15:21:15:23 | val | semmle.label | val | +| globalVars.c:16:2:16:12 | Store | semmle.label | Store | +| globalVars.c:24:11:24:14 | argv | semmle.label | argv | +| globalVars.c:24:11:24:14 | argv | semmle.label | argv | +| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:27:9:27:12 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | copy | semmle.label | copy | +| globalVars.c:30:15:30:18 | 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 *)... | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | +#select +| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:38:9:38:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:38:9:38:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:41:15:41:19 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:41:15:41:19 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format) | globalVars.c:24:11:24:14 | argv | argv | +| globalVars.c:50:9:50:13 | copy2 | globalVars.c:24:11:24:14 | argv | globalVars.c:50:9:50:13 | copy2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | globalVars.c:24:11:24:14 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected index d474364a0cc..62c36d0192d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected @@ -1,11 +1,157 @@ -| ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:61:8:61:11 | argv | argv | -| ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:68:8:68:11 | argv | argv | -| ifs.c:75:9:75:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:74:8:74:11 | argv | argv | -| ifs.c:81:9:81:10 | i2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:80:8:80:11 | argv | argv | -| ifs.c:87:9:87:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:86:8:86:11 | argv | argv | -| ifs.c:93:9:93:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:92:8:92:11 | argv | argv | -| ifs.c:99:9:99:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:98:8:98:11 | argv | argv | -| ifs.c:106:9:106:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:105:8:105:11 | argv | argv | -| ifs.c:112:9:112:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:111:8:111:11 | argv | argv | -| ifs.c:118:9:118:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:117:8:117:11 | argv | argv | -| ifs.c:124:9:124:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:123:8:123:11 | argv | argv | +edges +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +nodes +| ifs.c:61:8:61:11 | argv | semmle.label | argv | +| ifs.c:61:8:61:11 | argv | semmle.label | argv | +| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | +| ifs.c:68:8:68:11 | argv | semmle.label | argv | +| ifs.c:68:8:68:11 | argv | semmle.label | argv | +| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | +| ifs.c:74:8:74:11 | argv | semmle.label | argv | +| ifs.c:74:8:74:11 | argv | semmle.label | argv | +| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | +| ifs.c:80:8:80:11 | argv | semmle.label | argv | +| ifs.c:80:8:80:11 | argv | semmle.label | argv | +| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | +| ifs.c:86:8:86:11 | argv | semmle.label | argv | +| ifs.c:86:8:86:11 | argv | semmle.label | argv | +| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | +| ifs.c:92:8:92:11 | argv | semmle.label | argv | +| ifs.c:92:8:92:11 | argv | semmle.label | argv | +| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | +| ifs.c:98:8:98:11 | argv | semmle.label | argv | +| ifs.c:98:8:98:11 | argv | semmle.label | argv | +| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | +| ifs.c:105:8:105:11 | argv | semmle.label | argv | +| ifs.c:105:8:105:11 | argv | semmle.label | argv | +| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | +| ifs.c:111:8:111:11 | argv | semmle.label | argv | +| ifs.c:111:8:111:11 | argv | semmle.label | argv | +| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | +| ifs.c:117:8:117:11 | argv | semmle.label | argv | +| ifs.c:117:8:117:11 | argv | semmle.label | argv | +| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | +| ifs.c:123:8:123:11 | argv | semmle.label | argv | +| ifs.c:123:8:123:11 | argv | semmle.label | argv | +| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | +#select +| ifs.c:62:9:62:10 | c7 | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:61:8:61:11 | argv | argv | +| ifs.c:69:9:69:10 | c8 | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:68:8:68:11 | argv | argv | +| ifs.c:75:9:75:10 | i1 | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:74:8:74:11 | argv | argv | +| ifs.c:81:9:81:10 | i2 | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:80:8:80:11 | argv | argv | +| ifs.c:87:9:87:10 | i3 | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:86:8:86:11 | argv | argv | +| ifs.c:93:9:93:10 | i4 | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:92:8:92:11 | argv | argv | +| ifs.c:99:9:99:10 | i5 | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:98:8:98:11 | argv | argv | +| ifs.c:106:9:106:10 | i6 | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:105:8:105:11 | argv | argv | +| ifs.c:112:9:112:10 | i7 | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:111:8:111:11 | argv | argv | +| ifs.c:118:9:118:10 | i8 | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:117:8:117:11 | argv | argv | +| ifs.c:124:9:124:10 | i9 | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format) | ifs.c:123:8:123:11 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index f77bf73d52d..773a969e9ad 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -1,9 +1,138 @@ -| test.cpp:42:31:42:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:31:43:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:45:31:45:36 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:48:25:48:30 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:49:17:49:30 | new[] | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:21:52:27 | call to realloc | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | -| test.cpp:127:17:127:22 | call to malloc | This allocation size is derived from $@ and might overflow | test.cpp:123:25:123:30 | call to getenv | user input (getenv) | +edges +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | (size_t)... | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | +| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:123:18:123:31 | (const char *)... | test.cpp:127:24:127:41 | ... * ... | +| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | +| test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | +| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | +| test.cpp:132:19:132:32 | (const char *)... | test.cpp:134:10:134:27 | ... * ... | +| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | +| test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | +| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | +| test.cpp:138:19:138:32 | (const char *)... | test.cpp:142:11:142:28 | ... * ... | +| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | +| test.cpp:201:9:201:42 | Store | test.cpp:231:9:231:24 | call to get_tainted_size | +| test.cpp:201:14:201:19 | call to getenv | test.cpp:201:9:201:42 | Store | +| test.cpp:201:14:201:27 | (const char *)... | test.cpp:201:9:201:42 | Store | +| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | +| test.cpp:214:23:214:23 | s | test.cpp:215:21:215:21 | s | +| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | +| test.cpp:220:21:220:21 | s | test.cpp:221:21:221:21 | s | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | (size_t)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:235:11:235:20 | (size_t)... | +| test.cpp:227:24:227:29 | call to getenv | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:235:11:235:20 | (size_t)... | +| test.cpp:227:24:227:37 | (const char *)... | test.cpp:237:10:237:19 | (size_t)... | +| test.cpp:235:11:235:20 | (size_t)... | test.cpp:214:23:214:23 | s | +| test.cpp:237:10:237:19 | (size_t)... | test.cpp:220:21:220:21 | s | +nodes +| test.cpp:39:21:39:24 | argv | semmle.label | argv | +| test.cpp:39:21:39:24 | argv | semmle.label | argv | +| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:42:38:42:44 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:42:38:42:44 | tainted | semmle.label | tainted | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:43:38:43:63 | ... * ... | semmle.label | ... * ... | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:45:38:45:63 | ... + ... | semmle.label | ... + ... | +| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:48:32:48:35 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:48:32:48:35 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:49:26:49:29 | size | semmle.label | size | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:52:35:52:60 | ... * ... | semmle.label | ... * ... | +| test.cpp:123:18:123:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:123:18:123:31 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | +| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | +| test.cpp:127:24:127:41 | ... * ... | semmle.label | ... * ... | +| test.cpp:132:19:132:24 | call to getenv | semmle.label | call to getenv | +| test.cpp:132:19:132:32 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | +| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | +| test.cpp:134:10:134:27 | ... * ... | semmle.label | ... * ... | +| test.cpp:138:19:138:24 | call to getenv | semmle.label | call to getenv | +| test.cpp:138:19:138:32 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | +| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | +| test.cpp:142:11:142:28 | ... * ... | semmle.label | ... * ... | +| test.cpp:201:9:201:42 | Store | semmle.label | Store | +| test.cpp:201:14:201:19 | call to getenv | semmle.label | call to getenv | +| test.cpp:201:14:201:27 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:214:23:214:23 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:215:21:215:21 | s | semmle.label | s | +| test.cpp:220:21:220:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:221:21:221:21 | s | semmle.label | s | +| test.cpp:227:24:227:29 | call to getenv | semmle.label | call to getenv | +| test.cpp:227:24:227:37 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:229:9:229:18 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:229:9:229:18 | local_size | semmle.label | local_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:231:9:231:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | +| test.cpp:235:11:235:20 | (size_t)... | semmle.label | (size_t)... | +| test.cpp:237:10:237:19 | (size_t)... | semmle.label | (size_t)... | +#select +| test.cpp:42:31:42:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:42:38:42:44 | tainted | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:43:38:43:63 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:45:31:45:36 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:45:38:45:63 | ... + ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:48:25:48:30 | call to malloc | test.cpp:39:21:39:24 | argv | test.cpp:48:32:48:35 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:49:17:49:30 | new[] | test.cpp:39:21:39:24 | argv | test.cpp:49:26:49:29 | size | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:52:21:52:27 | call to realloc | test.cpp:39:21:39:24 | argv | test.cpp:52:35:52:60 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:39:21:39:24 | argv | user input (argv) | +| test.cpp:127:17:127:22 | call to malloc | test.cpp:123:18:123:23 | call to getenv | test.cpp:127:24:127:41 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:123:18:123:23 | call to getenv | user input (getenv) | +| test.cpp:134:3:134:8 | call to malloc | test.cpp:132:19:132:24 | call to getenv | test.cpp:134:10:134:27 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:132:19:132:24 | call to getenv | user input (getenv) | +| test.cpp:142:4:142:9 | call to malloc | test.cpp:138:19:138:24 | call to getenv | test.cpp:142:11:142:28 | ... * ... | This allocation size is derived from $@ and might overflow | test.cpp:138:19:138:24 | call to getenv | user input (getenv) | +| test.cpp:215:14:215:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:215:21:215:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:221:14:221:19 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:221:21:221:21 | s | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:229:2:229:7 | call to malloc | test.cpp:227:24:227:29 | call to getenv | test.cpp:229:9:229:18 | local_size | This allocation size is derived from $@ and might overflow | test.cpp:227:24:227:29 | call to getenv | user input (getenv) | +| test.cpp:231:2:231:7 | call to malloc | test.cpp:201:14:201:19 | call to getenv | test.cpp:231:9:231:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow | test.cpp:201:14:201:19 | call to getenv | user input (getenv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp index 5cd5f0c0246..cb21e8f1915 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/test.cpp @@ -5,8 +5,8 @@ typedef struct {} FILE; void *malloc(size_t size); void *realloc(void *ptr, size_t size); +void free(void *ptr); int atoi(const char *nptr); - struct MyStruct { char data[256]; @@ -39,10 +39,10 @@ int main(int argc, char **argv) { int tainted = atoi(argv[1]); MyStruct *arr1 = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD - MyStruct *arr2 = (MyStruct *)malloc(tainted); // BAD + MyStruct *arr2 = (MyStruct *)malloc(tainted); // DUBIOUS (not multiplied by anything) MyStruct *arr3 = (MyStruct *)malloc(tainted * sizeof(MyStruct)); // BAD MyStruct *arr4 = (MyStruct *)malloc(getTainted() * sizeof(MyStruct)); // BAD [NOT DETECTED] - MyStruct *arr5 = (MyStruct *)malloc(sizeof(MyStruct) + tainted); // BAD [NOT DETECTED] + MyStruct *arr5 = (MyStruct *)malloc(sizeof(MyStruct) + tainted); // DUBIOUS (not multiplied by anything) int size = tainted * 8; char *chars1 = (char *)malloc(size); // BAD @@ -52,7 +52,7 @@ int main(int argc, char **argv) { arr1 = (MyStruct *)realloc(arr1, sizeof(MyStruct) * tainted); // BAD size = 8; - chars3 = new char[size]; // GOOD [FALSE POSITIVE] + chars3 = new char[size]; // GOOD return 0; } @@ -120,9 +120,119 @@ int bounded(int x, int limit) { } void open_file_bounded () { - int size = size = atoi(getenv("USER")); + int size = atoi(getenv("USER")); int bounded_size = bounded(size, MAX_SIZE); - int* a = (int*)malloc(bounded_size); // GOOD - int* b = (int*)malloc(size); // BAD -} \ No newline at end of file + int* a = (int*)malloc(bounded_size * sizeof(int)); // GOOD + int* b = (int*)malloc(size * sizeof(int)); // BAD +} + +void more_bounded_tests() { + { + int size = atoi(getenv("USER")); + + malloc(size * sizeof(int)); // BAD + } + + { + int size = atoi(getenv("USER")); + + if (size > 0) + { + malloc(size * sizeof(int)); // BAD + } + } + + { + int size = atoi(getenv("USER")); + + if (size < 100) + { + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + } + } + + { + int size = atoi(getenv("USER")); + + if ((size > 0) && (size < 100)) + { + malloc(size * sizeof(int)); // GOOD + } + } + + { + int size = atoi(getenv("USER")); + + if ((100 > size) && (0 < size)) + { + malloc(size * sizeof(int)); // GOOD + } + } + + { + int size = atoi(getenv("USER")); + + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + + if ((size > 0) && (size < 100)) + { + // ... + } + } + + { + int size = atoi(getenv("USER")); + + if (size > 100) + { + malloc(size * sizeof(int)); // BAD [NOT DETECTED] + } + } +} + +size_t get_untainted_size() +{ + return 10 * sizeof(int); +} + +size_t get_tainted_size() +{ + return atoi(getenv("USER")) * sizeof(int); +} + +size_t get_bounded_size() +{ + size_t s = atoi(getenv("USER")) * sizeof(int); + + if (s < 0) { s = 0; } + if (s > 100) { s = 100; } + + return s; +} + +void *my_alloc(size_t s) { + void *ptr = malloc(s); // [UNHELPFUL RESULT] + + return ptr; +} + +void my_func(size_t s) { + void *ptr = malloc(s); // BAD + + free(ptr); +} + +void more_cases() { + int local_size = atoi(getenv("USER")) * sizeof(int); + + malloc(local_size); // BAD + malloc(get_untainted_size()); // GOOD + malloc(get_tainted_size()); // BAD + malloc(get_bounded_size()); // GOOD + + my_alloc(100); // GOOD + my_alloc(local_size); // BAD [NOT DETECTED IN CORRECT LOCATION] + my_func(100); // GOOD + my_func(local_size); // GOOD +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected index 860ef74fdff..f68464b6b38 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected @@ -1,9 +1,138 @@ -| test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value | -| test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value | -| test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value | -| test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value | -| test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value | -| test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value | -| test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value | -| test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value | -| test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value | +edges +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:61:5:61:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:60:13:60:16 | call to rand | test.c:62:5:62:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | +| test.cpp:8:9:8:12 | Store | test.cpp:24:11:24:18 | call to get_rand | +| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | +| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store | +| test.cpp:13:2:13:15 | Chi | test.cpp:30:13:30:14 | get_rand2 output argument | +| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi | +| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi | +| test.cpp:18:2:18:14 | Chi | test.cpp:36:13:36:13 | get_rand3 output argument | +| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi | +| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi | +| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | +| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | +| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r | +| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r | +| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r | +| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r | +nodes +| test.c:18:13:18:16 | call to rand | semmle.label | call to rand | +| test.c:18:13:18:16 | call to rand | semmle.label | call to rand | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:21:17:21:17 | r | semmle.label | r | +| test.c:34:13:34:18 | call to rand | semmle.label | call to rand | +| test.c:34:13:34:18 | call to rand | semmle.label | call to rand | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:35:5:35:5 | r | semmle.label | r | +| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... | +| test.c:39:13:39:21 | ... % ... | semmle.label | ... % ... | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:40:5:40:5 | r | semmle.label | r | +| test.c:44:13:44:16 | call to rand | semmle.label | call to rand | +| test.c:44:13:44:16 | call to rand | semmle.label | call to rand | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:45:5:45:5 | r | semmle.label | r | +| test.c:54:13:54:16 | call to rand | semmle.label | call to rand | +| test.c:54:13:54:16 | call to rand | semmle.label | call to rand | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:56:5:56:5 | r | semmle.label | r | +| test.c:60:13:60:16 | call to rand | semmle.label | call to rand | +| test.c:60:13:60:16 | call to rand | semmle.label | call to rand | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:61:5:61:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:62:5:62:5 | r | semmle.label | r | +| test.c:66:13:66:16 | call to rand | semmle.label | call to rand | +| test.c:66:13:66:16 | call to rand | semmle.label | call to rand | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:67:5:67:5 | r | semmle.label | r | +| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... | +| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:77:9:77:9 | r | semmle.label | r | +| test.c:99:14:99:19 | call to rand | semmle.label | call to rand | +| test.c:99:14:99:19 | call to rand | semmle.label | call to rand | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.c:100:5:100:5 | r | semmle.label | r | +| test.cpp:8:9:8:12 | Store | semmle.label | Store | +| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | +| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | +| test.cpp:13:2:13:15 | Chi | semmle.label | Chi | +| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand | +| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand | +| test.cpp:18:2:18:14 | Chi | semmle.label | Chi | +| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand | +| 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:25:7:25:7 | r | semmle.label | r | +| test.cpp:25:7:25:7 | r | semmle.label | r | +| test.cpp:30:13:30:14 | get_rand2 output argument | semmle.label | get_rand2 output argument | +| test.cpp:31:7:31:7 | r | semmle.label | r | +| test.cpp:31:7:31:7 | r | semmle.label | r | +| test.cpp:31:7:31:7 | r | semmle.label | r | +| test.cpp:36:13:36:13 | get_rand3 output argument | semmle.label | get_rand3 output argument | +| test.cpp:37:7:37:7 | r | semmle.label | r | +| test.cpp:37:7:37:7 | r | semmle.label | r | +| test.cpp:37:7:37:7 | r | semmle.label | r | +#select +| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value | +| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value | +| test.c:40:5:40:5 | r | test.c:39:13:39:21 | ... % ... | test.c:40:5:40:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:39:13:39:21 | ... % ... | Uncontrolled value | +| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value | +| test.c:56:5:56:5 | r | test.c:54:13:54:16 | call to rand | test.c:56:5:56:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:54:13:54:16 | call to rand | Uncontrolled value | +| test.c:67:5:67:5 | r | test.c:66:13:66:16 | call to rand | test.c:67:5:67:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:66:13:66:16 | call to rand | Uncontrolled value | +| test.c:77:9:77:9 | r | test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value | +| test.c:100:5:100:5 | r | test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value | +| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value | +| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | Uncontrolled value | +| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | Uncontrolled value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected index ded1524cfca..e2671c07952 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected @@ -1,3 +1,33 @@ -| test.cpp:20:7:20:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | -| test.cpp:31:7:31:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:27:25:27:30 | call to getenv | call to getenv | -| test.cpp:42:7:42:12 | call to strcmp | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:38:25:38:30 | call to getenv | call to getenv | +edges +| test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | +| test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | +| test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | +nodes +| test.cpp:16:25:16:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:20:14:20:20 | address | semmle.label | address | +| test.cpp:27:25:27:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:27:25:27:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:31:14:31:20 | address | semmle.label | address | +| test.cpp:38:25:38:30 | call to getenv | semmle.label | call to getenv | +| test.cpp:38:25:38:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:42:14:42:20 | address | semmle.label | address | +| test.cpp:42:14:42:20 | address | semmle.label | address | +| test.cpp:42:14:42:20 | address | semmle.label | address | +#select +| test.cpp:20:7:20:12 | call to strcmp | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | +| test.cpp:31:7:31:12 | call to strcmp | test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:27:25:27:30 | call to getenv | call to getenv | +| test.cpp:42:7:42:12 | call to strcmp | test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:38:25:38:30 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected index 30b971f13e7..f78d75eeed1 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected @@ -1 +1,13 @@ -| test.cpp:58:3:58:9 | call to sprintf | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (argv) | +edges +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | +nodes +| test.cpp:54:17:54:20 | argv | semmle.label | argv | +| test.cpp:54:17:54:20 | argv | semmle.label | argv | +| test.cpp:58:25:58:29 | input | semmle.label | input | +| test.cpp:58:25:58:29 | input | semmle.label | input | +| test.cpp:58:25:58:29 | input | semmle.label | input | +#select +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected index 0ae48831c80..cc5004047cf 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected @@ -1,2 +1,37 @@ -| test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... | -| test.cpp:41:10:41:38 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:42:8:42:26 | ... = ... | ... = ... | +edges +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:10:41:38 | ! ... | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:34 | call to getenv | test.cpp:41:11:41:38 | (bool)... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:10:24:35 | ! ... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:10:41:38 | ! ... | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:16 | call to strcmp | +| test.cpp:20:29:20:47 | (const char *)... | test.cpp:41:11:41:38 | (bool)... | +| test.cpp:24:11:24:16 | call to strcmp | test.cpp:24:10:24:35 | ! ... | +| test.cpp:24:11:24:16 | call to strcmp | test.cpp:24:11:24:35 | (bool)... | +| test.cpp:41:11:41:16 | call to strcmp | test.cpp:41:10:41:38 | ! ... | +| test.cpp:41:11:41:16 | call to strcmp | test.cpp:41:11:41:38 | (bool)... | +nodes +| test.cpp:20:29:20:34 | call to getenv | semmle.label | call to getenv | +| test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... | +| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:24:11:24:35 | (bool)... | semmle.label | (bool)... | +| test.cpp:24:11:24:35 | (bool)... | semmle.label | (bool)... | +| test.cpp:41:10:41:38 | ! ... | semmle.label | ! ... | +| test.cpp:41:11:41:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:41:11:41:16 | call to strcmp | semmle.label | call to strcmp | +| test.cpp:41:11:41:38 | (bool)... | semmle.label | (bool)... | +| test.cpp:41:11:41:38 | (bool)... | semmle.label | (bool)... | +#select +| test.cpp:24:10:24:35 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... | +| test.cpp:41:10:41:38 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:41:10:41:38 | ! ... | Reliance on untrusted input $@ to raise privilege at $@ | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:42:8:42:26 | ... = ... | ... = ... | diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected index 1644085ff12..ce056261514 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/AV Rule 114.expected @@ -4,9 +4,9 @@ | test.c:25:9:25:14 | ExprStmt | Function f4 should return a value of type int but does not return a value here | | test.c:39:9:39:14 | ExprStmt | Function f6 should return a value of type int but does not return a value here | | test.cpp:16:1:18:1 | { ... } | Function g2 should return a value of type MyValue but does not return a value here | -| test.cpp:48:2:48:26 | if (...) ... | Function g7 should return a value of type MyValue but does not return a value here | +| test.cpp:52:1:52:1 | return ... | Function g7 should return a value of type MyValue but does not return a value here | | test.cpp:74:1:76:1 | { ... } | Function g10 should return a value of type second but does not return a value here | | test.cpp:86:1:88:1 | { ... } | Function g12 should return a value of type second but does not return a value here | -| test.cpp:108:2:111:2 | if (...) ... | Function g14 should return a value of type int but does not return a value here | +| test.cpp:112:1:112:1 | return ... | Function g14 should return a value of type int but does not return a value here | | test.cpp:134:2:134:36 | ExprStmt | Function g16 should return a value of type int but does not return a value here | | test.cpp:141:3:141:37 | ExprStmt | Function g17 should return a value of type int but does not return a value here | diff --git a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp index 0dc0daf42c0..875c9ec4f75 100644 --- a/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp +++ b/cpp/ql/test/query-tests/jsf/4.13 Functions/AV Rule 114/test.cpp @@ -48,7 +48,7 @@ MyValue g7(bool c) if (c) return MyValue(7); DONOTHING DONOTHING - // BAD [the alert here is unfortunately placed] + // BAD } typedef void MYVOID; diff --git a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs index a2e59cf7ac3..b66fa4ff399 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs @@ -341,6 +341,8 @@ namespace Semmle.Extraction.Tests string cwd = @"C:\Project") { Actions.GetEnvironmentVariable["CODEQL_AUTOBUILDER_CSHARP_NO_INDEXING"] = "false"; + Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = ""; + Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = ""; Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_ROOT"] = @"C:\codeql\csharp"; Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa"; @@ -364,8 +366,7 @@ namespace Semmle.Extraction.Tests Actions.GetCurrentDirectory = cwd; Actions.IsWindows = isWindows; - var options = new AutobuildOptions(); - options.ReadEnvironment(Actions); + var options = new AutobuildOptions(Actions); return new Autobuilder(Actions, options); } diff --git a/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs index b5b3dfcf61d..f9c690c273b 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs @@ -7,10 +7,9 @@ { public BuildScript Analyse(Autobuilder builder, bool auto) { - (var javaHome, var dist) = - builder.CodeQLJavaHome != null ? - (builder.CodeQLJavaHome, builder.CodeQLExtractorCSharpRoot) : - (builder.SemmleJavaHome, builder.SemmleDist); + var javaHome = builder.JavaHome; + var dist = builder.Distribution; + var command = new CommandBuilder(builder.Actions). RunCommand(builder.Actions.PathCombine(javaHome, "bin", "java")). Argument("-jar"). diff --git a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs index 740b740f9fb..9786e4dcca6 100644 --- a/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs @@ -10,40 +10,40 @@ namespace Semmle.Autobuild public class AutobuildOptions { public readonly int SearchDepth = 3; - public string RootDirectory = null; - static readonly string prefix = "LGTM_INDEX_"; + public readonly string RootDirectory; + private const string prefix = "LGTM_INDEX_"; - public string VsToolsVersion; - public string MsBuildArguments; - public string MsBuildPlatform; - public string MsBuildConfiguration; - public string MsBuildTarget; - public string DotNetArguments; - public string DotNetVersion; - public string BuildCommand; - public string[] Solution; + public readonly string? VsToolsVersion; + public readonly string? MsBuildArguments; + public readonly string? MsBuildPlatform; + public readonly string? MsBuildConfiguration; + public readonly string? MsBuildTarget; + public readonly string? DotNetArguments; + public readonly string? DotNetVersion; + public readonly string? BuildCommand; + public readonly string[] Solution; - public bool IgnoreErrors; - public bool Buildless; - public bool AllSolutions; - public bool NugetRestore; + public readonly bool IgnoreErrors; + public readonly bool Buildless; + public readonly bool AllSolutions; + public readonly bool NugetRestore; - public Language Language; - public bool Indexing; + public readonly Language Language; + public readonly bool Indexing; /// /// Reads options from environment variables. /// Throws ArgumentOutOfRangeException for invalid arguments. /// - public void ReadEnvironment(IBuildActions actions) + public AutobuildOptions(IBuildActions actions) { RootDirectory = actions.GetCurrentDirectory(); VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION"); - MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVars(actions); + MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS")?.AsStringWithExpandedEnvVars(actions); MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM"); MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION"); MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET"); - DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVars(actions); + DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS")?.AsStringWithExpandedEnvVars(actions); DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION"); BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND"); Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]); @@ -60,7 +60,7 @@ namespace Semmle.Autobuild public static class OptionsExtensions { - public static bool AsBool(this string value, string param, bool defaultValue) + public static bool AsBool(this string? value, string param, bool defaultValue) { if (value == null) return defaultValue; switch (value.ToLower()) @@ -80,7 +80,7 @@ namespace Semmle.Autobuild } } - public static Language AsLanguage(this string key) + public static Language AsLanguage(this string? key) { switch (key) { @@ -95,7 +95,7 @@ namespace Semmle.Autobuild } } - public static string[] AsListWithExpandedEnvVars(this string value, IBuildActions actions, string[] defaultValue) + public static string[] AsListWithExpandedEnvVars(this string? value, IBuildActions actions, string[] defaultValue) { if (value == null) return defaultValue; diff --git a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs index 73e6fcd181f..f6dbdae788c 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs @@ -20,6 +20,14 @@ namespace Semmle.Autobuild BuildScript Analyse(Autobuilder builder, bool auto); } + /// + /// Exception indicating that environment variables are missing or invalid. + /// + class InvalidEnvironmentException : Exception + { + public InvalidEnvironmentException(string m) : base(m) { } + } + /// /// Main application logic, containing all data /// gathered from the project and filesystem. @@ -69,7 +77,7 @@ namespace Semmle.Autobuild /// List of project/solution files to build. /// public IList ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value; - readonly Lazy> projectsOrSolutionsToBuildLazy; + private readonly Lazy> projectsOrSolutionsToBuildLazy; /// /// Holds if a given path was found. @@ -129,7 +137,7 @@ namespace Semmle.Autobuild projectsOrSolutionsToBuildLazy = new Lazy>(() => { - List ret; + List? ret; if (options.Solution.Any()) { ret = new List(); @@ -143,7 +151,7 @@ namespace Semmle.Autobuild return ret; } - IEnumerable FindFiles(string extension, Func create) + IEnumerable? FindFiles(string extension, Func create) { var matchingFiles = GetExtensions(extension). Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)). @@ -177,19 +185,34 @@ namespace Semmle.Autobuild }); CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT"); - - CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME"); - SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST"); - - SemmleJavaHome = Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME"); - SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS"); - if (CodeQLExtractorCSharpRoot == null && SemmleDist == null) - Log(Severity.Error, "The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set."); + JavaHome = + Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME") ?? + Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_JAVA_HOME or SEMMLE_JAVA_HOME has not been set."); + + Distribution = + CodeQLExtractorCSharpRoot ?? + SemmleDist ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_ROOT or SEMMLE_DIST has not been set."); + + TrapDir = + Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? + Actions.GetEnvironmentVariable("TRAP_FOLDER") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_TRAP_DIR or TRAP_FOLDER has not been set."); + + SourceArchiveDir = + Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? + Actions.GetEnvironmentVariable("SOURCE_ARCHIVE") ?? + throw new InvalidEnvironmentException("The environment variable CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR or SOURCE_ARCHIVE has not been set."); } + private string TrapDir { get; } + + private string SourceArchiveDir { get; } + readonly ILogger logger = new ConsoleLogger(Verbosity.Info); /// @@ -271,9 +294,9 @@ namespace Semmle.Autobuild break; case CSharpBuildStrategy.Auto: var cleanTrapFolder = - BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER")); + BuildScript.DeleteDirectory(TrapDir); var cleanSourceArchive = - BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE")); + BuildScript.DeleteDirectory(SourceArchiveDir); var tryCleanExtractorArgsLogs = BuildScript.Create(actions => { @@ -376,38 +399,33 @@ namespace Semmle.Autobuild /// /// Value of CODEQL_EXTRACTOR_CSHARP_ROOT environment variable. /// - public string CodeQLExtractorCSharpRoot { get; private set; } - - /// - /// Value of CODEQL_JAVA_HOME environment variable. - /// - public string CodeQLJavaHome { get; private set; } + private string? CodeQLExtractorCSharpRoot { get; } /// /// Value of SEMMLE_DIST environment variable. /// - public string SemmleDist { get; private set; } + private string? SemmleDist { get; } - /// - /// Value of SEMMLE_JAVA_HOME environment variable. - /// - public string SemmleJavaHome { get; private set; } + public string Distribution { get; } + + public string JavaHome { get; } /// /// Value of SEMMLE_PLATFORM_TOOLS environment variable. /// - public string SemmlePlatformTools { get; private set; } + public string? SemmlePlatformTools { get; } /// /// The absolute path of the odasa executable. + /// null if we are running in CodeQL. /// - public string Odasa => SemmleDist == null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa"); + public string? Odasa => SemmleDist is null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa"); /// /// Construct a command that executed the given wrapped in /// an odasa --index, unless indexing has been disabled, in which case /// is run directly. /// - internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd); + internal CommandBuilder MaybeIndex(CommandBuilder builder, string cmd) => Options.Indexing && !(Odasa is null) ? builder.IndexCommand(Odasa, cmd) : builder.RunCommand(cmd); } } diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs index 837f6e3f69e..7bc4b9b7591 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs @@ -21,7 +21,7 @@ namespace Semmle.Autobuild /// Additional environment variables. /// The lines of stdout. /// The process exit code. - int RunProcess(string exe, string args, string workingDirectory, IDictionary env, out IList stdOut); + int RunProcess(string exe, string args, string? workingDirectory, IDictionary? env, out IList stdOut); /// /// Runs a process but does not capture its output. @@ -31,7 +31,7 @@ namespace Semmle.Autobuild /// The working directory (null for current directory). /// Additional environment variables. /// The process exit code. - int RunProcess(string exe, string args, string workingDirectory, IDictionary env); + int RunProcess(string exe, string args, string? workingDirectory, IDictionary? env); /// /// Tests whether a file exists, File.Exists(). @@ -63,7 +63,7 @@ namespace Semmle.Autobuild /// /// The name of the variable. /// The string value, or null if the variable is not defined. - string GetEnvironmentVariable(string name); + string? GetEnvironmentVariable(string name); /// /// Gets the current directory, Directory.GetCurrentDirectory(). @@ -130,7 +130,7 @@ namespace Semmle.Autobuild bool IBuildActions.FileExists(string file) => File.Exists(file); - ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workingDirectory, IDictionary environment, bool redirectStandardOutput) + ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary? environment, bool redirectStandardOutput) { var pi = new ProcessStartInfo(exe, arguments) { @@ -146,7 +146,7 @@ namespace Semmle.Autobuild return pi; } - int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment) + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? environment) { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false); using (var p = Process.Start(pi)) @@ -156,7 +156,7 @@ namespace Semmle.Autobuild } } - int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment, out IList stdOut) + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? environment, out IList stdOut) { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true); return pi.ReadOutput(out stdOut); @@ -166,7 +166,7 @@ namespace Semmle.Autobuild bool IBuildActions.DirectoryExists(string dir) => Directory.Exists(dir); - string IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name); + string? IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name); string IBuildActions.GetCurrentDirectory() => Directory.GetCurrentDirectory(); diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs index e7e2c9255dd..80a819f403e 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs @@ -40,7 +40,7 @@ namespace Semmle.Autobuild chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); - var dir = Path.GetDirectoryName(scriptPath); + string? dir = Path.GetDirectoryName(scriptPath); // A specific .NET Core version may be required return chmodScript & DotNetRule.WithDotNet(builder, environment => diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs index 93ea941d58b..5c60f4110ba 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs @@ -48,8 +48,9 @@ namespace Semmle.Autobuild class BuildCommand : BuildScript { - readonly string exe, arguments, workingDirectory; - readonly IDictionary environment; + readonly string exe, arguments; + readonly string? workingDirectory; + readonly IDictionary? environment; readonly bool silent; /// @@ -60,7 +61,7 @@ namespace Semmle.Autobuild /// Whether this command should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public BuildCommand(string exe, string argumentsOpt, bool silent, string workingDirectory = null, IDictionary environment = null) + public BuildCommand(string exe, string argumentsOpt, bool silent, string? workingDirectory = null, IDictionary? environment = null) { this.exe = exe; this.arguments = argumentsOpt ?? ""; @@ -131,8 +132,8 @@ namespace Semmle.Autobuild class BindBuildScript : BuildScript { readonly BuildScript s1; - readonly Func, int, BuildScript> s2a; - readonly Func s2b; + readonly Func, int, BuildScript>? s2a; + readonly Func? s2b; public BindBuildScript(BuildScript s1, Func, int, BuildScript> s2) { this.s1 = s1; @@ -154,14 +155,19 @@ namespace Semmle.Autobuild return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack); } - ret1 = s1.Run(actions, startCallback, exitCallBack); - return s2b(ret1).Run(actions, startCallback, exitCallBack); + if (s2b != null) + { + ret1 = s1.Run(actions, startCallback, exitCallBack); + return s2b(ret1).Run(actions, startCallback, exitCallBack); + } + + throw new InvalidOperationException("Unexpected error"); } public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) { var ret1 = s1.Run(actions, startCallback, exitCallBack, out var stdout1); - var ret2 = (s2a != null ? s2a(stdout1, ret1) : s2b(ret1)).Run(actions, startCallback, exitCallBack, out var stdout2); + var ret2 = (s2a != null ? s2a(stdout1, ret1) : s2b!(ret1)).Run(actions, startCallback, exitCallBack, out var stdout2); var @out = new List(); @out.AddRange(stdout1); @out.AddRange(stdout2); @@ -177,7 +183,7 @@ namespace Semmle.Autobuild /// Whether the executable should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public static BuildScript Create(string exe, string argumentsOpt, bool silent, string workingDirectory, IDictionary environment) => + public static BuildScript Create(string exe, string argumentsOpt, bool silent, string? workingDirectory, IDictionary? environment) => new BuildCommand(exe, argumentsOpt, silent, workingDirectory, environment); /// diff --git a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs index 264436a1ea7..353f132c6ec 100644 --- a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Text; @@ -13,10 +13,10 @@ namespace Semmle.Autobuild readonly StringBuilder arguments; bool firstCommand; - string executable; + string? executable; readonly EscapeMode escapingMode; - readonly string workingDirectory; - readonly IDictionary environment; + readonly string? workingDirectory; + readonly IDictionary? environment; readonly bool silent; /// @@ -25,7 +25,7 @@ namespace Semmle.Autobuild /// The working directory (null for current directory). /// Additional environment variables. /// Whether this command should be run silently. - public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDictionary environment = null, bool silent = false) + public CommandBuilder(IBuildActions actions, string? workingDirectory = null, IDictionary? environment = null, bool silent = false) { arguments = new StringBuilder(); if (actions.IsWindows()) @@ -50,7 +50,7 @@ namespace Semmle.Autobuild RunCommand(odasa, "index --auto"); } - public CommandBuilder CallBatFile(string batFile, string argumentsOpt = null) + public CommandBuilder CallBatFile(string batFile, string? argumentsOpt = null) { NextCommand(); arguments.Append(" CALL"); @@ -66,7 +66,7 @@ namespace Semmle.Autobuild /// The command to run. /// Additional arguments. /// this for chaining calls. - public CommandBuilder IndexCommand(string odasa, string command, string argumentsOpt = null) + public CommandBuilder IndexCommand(string odasa, string command, string? argumentsOpt = null) { OdasaIndex(odasa); QuoteArgument(command); @@ -151,7 +151,7 @@ namespace Semmle.Autobuild arguments.Append(' '); } - public CommandBuilder Argument(string argumentsOpt) + public CommandBuilder Argument(string? argumentsOpt) { if (argumentsOpt != null) { @@ -169,7 +169,7 @@ namespace Semmle.Autobuild arguments.Append(" &&"); } - public CommandBuilder RunCommand(string exe, string argumentsOpt = null, bool quoteExe = true) + public CommandBuilder RunCommand(string exe, string? argumentsOpt = null, bool quoteExe = true) { var (exe0, arg0) = escapingMode == EscapeMode.Process && exe.EndsWith(".exe", System.StringComparison.Ordinal) @@ -196,6 +196,14 @@ namespace Semmle.Autobuild /// /// Returns a build script that contains just this command. /// - public BuildScript Script => BuildScript.Create(executable, arguments.ToString(), silent, workingDirectory, environment); + public BuildScript Script + { + get + { + if (executable is null) + throw new System.InvalidOperationException("executable is null"); + return BuildScript.Create(executable, arguments.ToString(), silent, workingDirectory, environment); + } + } } } diff --git a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs index f3b81665fca..21215af8434 100644 --- a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs @@ -56,13 +56,13 @@ namespace Semmle.Autobuild }); } - static BuildScript WithDotNet(Autobuilder builder, Func, bool, BuildScript> f) + static BuildScript WithDotNet(Autobuilder builder, Func?, bool, BuildScript> f) { - var installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet"); + string? installDir = builder.Actions.PathCombine(builder.Options.RootDirectory, ".dotnet"); var installScript = DownloadDotNet(builder, installDir); return BuildScript.Bind(installScript, installed => { - Dictionary env; + Dictionary? env; if (installed == 0) { // The installation succeeded, so use the newly installed .NET Core @@ -120,7 +120,7 @@ namespace Semmle.Autobuild /// variables needed by the installed .NET Core (null when no variables /// are needed). /// - public static BuildScript WithDotNet(Autobuilder builder, Func, BuildScript> f) + public static BuildScript WithDotNet(Autobuilder builder, Func?, BuildScript> f) => WithDotNet(builder, (_1, env, _2) => f(env)); /// @@ -265,10 +265,10 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return listSdks.Script; } - static string DotNetCommand(IBuildActions actions, string dotNetPath) => + static string DotNetCommand(IBuildActions actions, string? dotNetPath) => dotNetPath != null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet"; - BuildScript GetInfoCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + BuildScript GetInfoCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var info = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -276,7 +276,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return info.Script; } - CommandBuilder GetCleanCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var clean = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -284,7 +284,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return clean; } - CommandBuilder GetRestoreCommand(IBuildActions actions, string dotNetPath, IDictionary environment) + CommandBuilder GetRestoreCommand(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var restore = new CommandBuilder(actions, null, environment). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -292,7 +292,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; return restore; } - static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string dotNetPath, IDictionary environment) + static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string? dotNetPath, IDictionary? environment) { var listSdks = new CommandBuilder(actions, environment: environment, silent: true). RunCommand(DotNetCommand(actions, dotNetPath)). @@ -309,7 +309,7 @@ Invoke-Command -ScriptBlock $ScriptBlock"; /// hence the need for CLR tracing), by adding a /// `/p:UseSharedCompilation=false` argument. /// - BuildScript GetBuildScript(Autobuilder builder, string dotNetPath, IDictionary environment, bool compatibleClr, string projOrSln) + BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary? environment, bool compatibleClr, string projOrSln) { var build = new CommandBuilder(builder.Actions, null, environment); var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, dotNetPath)). diff --git a/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs index 4e435f4bb9f..569f9f183eb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs @@ -74,10 +74,10 @@ namespace Semmle.Autobuild string target = builder.Options.MsBuildTarget != null ? builder.Options.MsBuildTarget : "rebuild"; - string platform = builder.Options.MsBuildPlatform != null + string? platform = builder.Options.MsBuildPlatform != null ? builder.Options.MsBuildPlatform : projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null; - string configuration = builder.Options.MsBuildConfiguration != null + string? configuration = builder.Options.MsBuildConfiguration != null ? builder.Options.MsBuildConfiguration : projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null; @@ -103,9 +103,9 @@ namespace Semmle.Autobuild /// /// Returns null when no version is specified. /// - public static VcVarsBatFile GetVcVarsBatFile(Autobuilder builder) + public static VcVarsBatFile? GetVcVarsBatFile(Autobuilder builder) { - VcVarsBatFile vsTools = null; + VcVarsBatFile? vsTools = null; if (builder.Options.VsToolsVersion != null) { diff --git a/csharp/autobuilder/Semmle.Autobuild/Program.cs b/csharp/autobuilder/Semmle.Autobuild/Program.cs index c4542864a09..e4bccb0e626 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Program.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Program.cs @@ -6,23 +6,27 @@ namespace Semmle.Autobuild { static int Main() { - var options = new AutobuildOptions(); - var actions = SystemBuildActions.Instance; try { - options.ReadEnvironment(actions); + var actions = SystemBuildActions.Instance; + var options = new AutobuildOptions(actions); + try + { + Console.WriteLine($"Semmle autobuilder for {options.Language}"); + var builder = new Autobuilder(actions, options); + return builder.AttemptBuild(); + } + catch(InvalidEnvironmentException ex) + { + Console.WriteLine("The environment is invalid: {0}", ex.Message); + } } catch (ArgumentOutOfRangeException ex) { Console.WriteLine("The value \"{0}\" for parameter \"{1}\" is invalid", ex.ActualValue, ex.ParamName); } - - var builder = new Autobuilder(actions, options); - - Console.WriteLine($"Semmle autobuilder for {options.Language}"); - - return builder.AttemptBuild(); + return 1; } } } diff --git a/csharp/autobuilder/Semmle.Autobuild/Project.cs b/csharp/autobuilder/Semmle.Autobuild/Project.cs index 0080f170c54..415ddcbc0f0 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Project.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Project.cs @@ -82,7 +82,7 @@ namespace Semmle.Autobuild foreach (var include in projectFileIncludes.Concat(projectFilesIncludes)) { var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries)); - ret.Add(new Project(builder, builder.Actions.PathCombine(Path.GetDirectoryName(this.FullPath), includePath))); + ret.Add(new Project(builder, builder.Actions.PathCombine(DirectoryName, includePath))); } return ret; }); diff --git a/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs index 53025345b69..13859a8c0eb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs +++ b/csharp/autobuilder/Semmle.Autobuild/ProjectOrSolution.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using System.Linq; namespace Semmle.Autobuild @@ -24,6 +25,8 @@ namespace Semmle.Autobuild { public string FullPath { get; private set; } + public string DirectoryName => Path.GetDirectoryName(FullPath) ?? ""; + protected ProjectOrSolution(Autobuilder builder, string path) { FullPath = builder.Actions.GetFullPath(path); diff --git a/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj index 5e3f2295ad0..63aab3b29fb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj +++ b/csharp/autobuilder/Semmle.Autobuild/Semmle.Autobuild.csproj @@ -9,6 +9,7 @@ false win-x64;linux-x64;osx-x64 + enable diff --git a/csharp/autobuilder/Semmle.Autobuild/Solution.cs b/csharp/autobuilder/Semmle.Autobuild/Solution.cs index 661f46199f8..0429b9f420c 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Solution.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Solution.cs @@ -43,7 +43,7 @@ namespace Semmle.Autobuild /// class Solution : ProjectOrSolution, ISolution { - readonly SolutionFile solution; + readonly SolutionFile? solution; readonly IEnumerable includedProjects; public override IEnumerable IncludedProjects => includedProjects; @@ -81,7 +81,7 @@ namespace Semmle.Autobuild includedProjects = solution.ProjectsInOrder. Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat). - Select(p => builder.Actions.PathCombine(Path.GetDirectoryName(path), builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries)))). + Select(p => builder.Actions.PathCombine(DirectoryName, builder.Actions.PathCombine(p.RelativePath.Split('\\', StringSplitOptions.RemoveEmptyEntries)))). Select(p => new Project(builder, p)). ToArray(); } diff --git a/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs index 366ce1f08fc..26bc84bb601 100644 --- a/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/StandaloneBuildRule.cs @@ -1,6 +1,4 @@ -using System.IO; - -namespace Semmle.Autobuild +namespace Semmle.Autobuild { /// /// Build using standalone extraction. @@ -9,8 +7,11 @@ namespace Semmle.Autobuild { public BuildScript Analyse(Autobuilder builder, bool auto) { - BuildScript GetCommand(string solution) + BuildScript GetCommand(string? solution) { + if (builder.SemmlePlatformTools is null) + return BuildScript.Failure; + var standalone = builder.Actions.PathCombine(builder.SemmlePlatformTools, "csharp", "Semmle.Extraction.CSharp.Standalone"); var cmd = new CommandBuilder(builder.Actions); cmd.RunCommand(standalone); diff --git a/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs index 5814c2b63d2..d9b05dbe0a9 100644 --- a/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/XmlBuildRule.cs @@ -7,7 +7,7 @@ { public BuildScript Analyse(Autobuilder builder, bool auto) { - if (!builder.Options.Indexing) + if (!builder.Options.Indexing || builder.Odasa is null) return BuildScript.Success; var command = new CommandBuilder(builder.Actions). diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs index db2664bf4c9..f93911b8a38 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/AssemblyCache.cs @@ -163,7 +163,19 @@ namespace Semmle.BuildAnalyser /// /// The filename to query. /// The assembly info. - public AssemblyInfo GetAssemblyInfo(string filepath) => assemblyInfo[filepath]; + public AssemblyInfo GetAssemblyInfo(string filepath) + { + if(assemblyInfo.TryGetValue(filepath, out var info)) + { + return info; + } + else + { + info = AssemblyInfo.ReadFromFile(filepath); + assemblyInfo.Add(filepath, info); + return info; + } + } // List of pending DLLs to index. readonly List dlls = new List(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs index b0ef328bcd0..2894222ca89 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/BuildAnalysis.cs @@ -1,10 +1,13 @@ -using System; +using Semmle.Util; +using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; -using Semmle.Util; using Semmle.Extraction.CSharp.Standalone; +using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Text; +using System.Security.Cryptography; namespace Semmle.BuildAnalyser { @@ -43,19 +46,18 @@ namespace Semmle.BuildAnalyser /// /// Main implementation of the build analysis. /// - class BuildAnalysis : IBuildAnalysis + class BuildAnalysis : IBuildAnalysis, IDisposable { - readonly AssemblyCache assemblyCache; - readonly NugetPackages nuget; - readonly IProgressMonitor progressMonitor; - HashSet usedReferences = new HashSet(); - readonly HashSet usedSources = new HashSet(); - readonly HashSet missingSources = new HashSet(); - readonly Dictionary unresolvedReferences = new Dictionary(); - readonly DirectoryInfo sourceDir; - int failedProjects, succeededProjects; - readonly string[] allSources; - int conflictedReferences = 0; + private readonly AssemblyCache assemblyCache; + private readonly NugetPackages nuget; + private readonly IProgressMonitor progressMonitor; + private readonly IDictionary usedReferences = new ConcurrentDictionary(); + private readonly IDictionary sources = new ConcurrentDictionary(); + private readonly IDictionary unresolvedReferences = new ConcurrentDictionary(); + private readonly DirectoryInfo sourceDir; + private int failedProjects, succeededProjects; + private readonly string[] allSources; + private int conflictedReferences = 0; /// /// Performs a C# build analysis. @@ -64,6 +66,8 @@ namespace Semmle.BuildAnalyser /// Display of analysis progress. public BuildAnalysis(Options options, IProgressMonitor progress) { + var startTime = DateTime.Now; + progressMonitor = progress; sourceDir = new DirectoryInfo(options.SrcDir); @@ -74,36 +78,43 @@ namespace Semmle.BuildAnalyser Where(d => !options.ExcludesFile(d)). ToArray(); - var dllDirNames = options.DllDirs.Select(Path.GetFullPath); + var dllDirNames = options.DllDirs.Select(Path.GetFullPath).ToList(); + PackageDirectory = new TemporaryDirectory(ComputeTempDirectory(sourceDir.FullName)); if (options.UseNuGet) { - nuget = new NugetPackages(sourceDir.FullName); - ReadNugetFiles(); - dllDirNames = dllDirNames.Concat(Enumerators.Singleton(nuget.PackageDirectory)); + try + { + nuget = new NugetPackages(sourceDir.FullName, PackageDirectory); + ReadNugetFiles(); + } + catch(FileNotFoundException) + { + progressMonitor.MissingNuGet(); + } } // Find DLLs in the .Net Framework if (options.ScanNetFrameworkDlls) { - dllDirNames = dllDirNames.Concat(Runtime.Runtimes.Take(1)); + dllDirNames.Add(Runtime.Runtimes.First()); } - assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); + // These files can sometimes prevent `dotnet restore` from working correctly. + using (new FileRenamer(sourceDir.GetFiles("global.json", SearchOption.AllDirectories))) + using (new FileRenamer(sourceDir.GetFiles("Directory.Build.props", SearchOption.AllDirectories))) + { + var solutions = options.SolutionFile != null ? + new[] { options.SolutionFile } : + sourceDir.GetFiles("*.sln", SearchOption.AllDirectories).Select(d => d.FullName); - // Analyse all .csproj files in the source tree. - if (options.SolutionFile != null) - { - AnalyseSolution(options.SolutionFile); - } - else if (options.AnalyseCsProjFiles) - { - AnalyseProjectFiles(); - } + RestoreSolutions(solutions); + dllDirNames.Add(PackageDirectory.DirInfo.FullName); + assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress); + AnalyseSolutions(solutions); - if (!options.AnalyseCsProjFiles) - { - usedReferences = new HashSet(assemblyCache.AllAssemblies.Select(a => a.Filename)); + foreach (var filename in assemblyCache.AllAssemblies.Select(a => a.Filename)) + UseReference(filename); } ResolveConflicts(); @@ -114,7 +125,7 @@ namespace Semmle.BuildAnalyser } // Output the findings - foreach (var r in usedReferences) + foreach (var r in usedReferences.Keys) { progressMonitor.ResolvedReference(r); } @@ -132,7 +143,27 @@ namespace Semmle.BuildAnalyser UnresolvedReferences.Count(), conflictedReferences, succeededProjects + failedProjects, - failedProjects); + failedProjects, + DateTime.Now - startTime); + } + + /// + /// Computes a unique temp directory for the packages associated + /// with this source tree. Use a SHA1 of the directory name. + /// + /// + /// The full path of the temp directory. + private static string ComputeTempDirectory(string srcDir) + { + var bytes = Encoding.Unicode.GetBytes(srcDir); + + using var sha1 = new SHA1CryptoServiceProvider(); + var sha = sha1.ComputeHash(bytes); + var sb = new StringBuilder(); + foreach (var b in sha.Take(8)) + sb.AppendFormat("{0:x2}", b); + + return Path.Combine(Path.GetTempPath(), "GitHub", "packages", sb.ToString()); } /// @@ -143,7 +174,7 @@ namespace Semmle.BuildAnalyser void ResolveConflicts() { var sortedReferences = usedReferences. - Select(r => assemblyCache.GetAssemblyInfo(r)). + Select(r => assemblyCache.GetAssemblyInfo(r.Key)). OrderBy(r => r.Version). ToArray(); @@ -154,7 +185,9 @@ namespace Semmle.BuildAnalyser finalAssemblyList[r.Name] = r; // Update the used references list - usedReferences = new HashSet(finalAssemblyList.Select(r => r.Value.Filename)); + usedReferences.Clear(); + foreach (var r in finalAssemblyList.Select(r => r.Value.Filename)) + UseReference(r); // Report the results foreach (var r in sortedReferences) @@ -183,7 +216,7 @@ namespace Semmle.BuildAnalyser /// The filename of the reference. void UseReference(string reference) { - usedReferences.Add(reference); + usedReferences[reference] = true; } /// @@ -192,25 +225,18 @@ namespace Semmle.BuildAnalyser /// The source file. void UseSource(FileInfo sourceFile) { - if (sourceFile.Exists) - { - usedSources.Add(sourceFile.FullName); - } - else - { - missingSources.Add(sourceFile.FullName); - } + sources[sourceFile.FullName] = sourceFile.Exists; } /// /// The list of resolved reference files. /// - public IEnumerable ReferenceFiles => this.usedReferences; + public IEnumerable ReferenceFiles => this.usedReferences.Keys; /// /// The list of source files used in projects. /// - public IEnumerable ProjectSourceFiles => usedSources; + public IEnumerable ProjectSourceFiles => sources.Where(s => s.Value).Select(s => s.Key); /// /// All of the source files in the source directory. @@ -226,7 +252,7 @@ namespace Semmle.BuildAnalyser /// List of source files which were mentioned in project files but /// do not exist on the file system. /// - public IEnumerable MissingSourceFiles => missingSources; + public IEnumerable MissingSourceFiles => sources.Where(s => !s.Value).Select(s => s.Key); /// /// Record that a particular reference couldn't be resolved. @@ -239,74 +265,101 @@ namespace Semmle.BuildAnalyser unresolvedReferences[id] = projectFile; } - /// - /// Performs an analysis of all .csproj files. - /// - void AnalyseProjectFiles() - { - AnalyseProjectFiles(sourceDir.GetFiles("*.csproj", SearchOption.AllDirectories)); - } + readonly TemporaryDirectory PackageDirectory; /// /// Reads all the source files and references from the given list of projects. /// /// The list of projects to analyse. - void AnalyseProjectFiles(FileInfo[] projectFiles) + void AnalyseProjectFiles(IEnumerable projectFiles) { - progressMonitor.AnalysingProjectFiles(projectFiles.Count()); - foreach (var proj in projectFiles) + AnalyseProject(proj); + } + + void AnalyseProject(FileInfo project) + { + if(!project.Exists) { - try - { - var csProj = new CsProjFile(proj); + progressMonitor.MissingProject(project.FullName); + return; + } - foreach (var @ref in csProj.References) - { - AssemblyInfo resolved = assemblyCache.ResolveReference(@ref); - if (!resolved.Valid) - { - UnresolvedReference(@ref, proj.FullName); - } - else - { - UseReference(resolved.Filename); - } - } + try + { + var csProj = new CsProjFile(project); - foreach (var src in csProj.Sources) - { - // Make a note of which source files the projects use. - // This information doesn't affect the build but is dumped - // as diagnostic output. - UseSource(new FileInfo(src)); - } - ++succeededProjects; - } - catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] + foreach (var @ref in csProj.References) { - ++failedProjects; - progressMonitor.FailedProjectFile(proj.FullName, ex.Message); + AssemblyInfo resolved = assemblyCache.ResolveReference(@ref); + if (!resolved.Valid) + { + UnresolvedReference(@ref, project.FullName); + } + else + { + UseReference(resolved.Filename); + } } + + foreach (var src in csProj.Sources) + { + // Make a note of which source files the projects use. + // This information doesn't affect the build but is dumped + // as diagnostic output. + UseSource(new FileInfo(src)); + } + + ++succeededProjects; + } + catch (Exception ex) // lgtm[cs/catch-of-all-exceptions] + { + ++failedProjects; + progressMonitor.FailedProjectFile(project.FullName, ex.Message); + } + + } + + void Restore(string projectOrSolution) + { + int exit = DotNet.RestoreToDirectory(projectOrSolution, PackageDirectory.DirInfo.FullName); + switch(exit) + { + case 0: + case 1: + // No errors + break; + default: + progressMonitor.CommandFailed("dotnet", $"restore \"{projectOrSolution}\"", exit); + break; } } - /// - /// Delete packages directory. - /// - public void Cleanup() + public void RestoreSolutions(IEnumerable solutions) { - if (nuget != null) nuget.Cleanup(progressMonitor); + Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, Restore); } - /// - /// Analyse all project files in a given solution only. - /// - /// The filename of the solution. - public void AnalyseSolution(string solutionFile) + public void AnalyseSolutions(IEnumerable solutions) { - var sln = new SolutionFile(solutionFile); - AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).ToArray()); + Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 } , solutionFile => + { + try + { + var sln = new SolutionFile(solutionFile); + progressMonitor.AnalysingSolution(solutionFile); + AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).Where(p => p.Exists)); + } + catch (Microsoft.Build.Exceptions.InvalidProjectFileException ex) + { + progressMonitor.FailedProjectFile(solutionFile, ex.BaseMessage); + } + }); + } + + public void Dispose() + { + PackageDirectory?.Dispose(); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs index 2c9e72c1eaa..1083c9b6257 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/CsProjFile.cs @@ -10,12 +10,18 @@ namespace Semmle.BuildAnalyser /// class CsProjFile { + private string Filename { get; } + + private string Directory => Path.GetDirectoryName(Filename); + /// /// Reads the .csproj file. /// /// The .csproj file. public CsProjFile(FileInfo filename) { + Filename = filename.FullName; + try { // This can fail if the .csproj is invalid or has @@ -39,7 +45,7 @@ namespace Semmle.BuildAnalyser /// and there seems to be no way to make it succeed. Fails on Linux. /// /// The file to read. - public void ReadMsBuildProject(FileInfo filename) + private void ReadMsBuildProject(FileInfo filename) { var msbuildProject = new Microsoft.Build.Execution.ProjectInstance(filename.FullName); @@ -62,7 +68,7 @@ namespace Semmle.BuildAnalyser /// fallback if ReadMsBuildProject() fails. /// /// The .csproj file. - public void ReadProjectFileAsXml(FileInfo filename) + private void ReadProjectFileAsXml(FileInfo filename) { var projFile = new XmlDocument(); var mgr = new XmlNamespaceManager(projFile.NameTable); @@ -71,22 +77,48 @@ namespace Semmle.BuildAnalyser var projDir = filename.Directory; var root = projFile.DocumentElement; - references = - root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr). - NodeList(). - Select(node => node.Value). - ToArray(); + // Figure out if it's dotnet core - var relativeCsIncludes = - root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr). - NodeList(). - Select(node => node.Value). - ToArray(); + bool netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk"; - csFiles = relativeCsIncludes. - Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). - Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))). - ToArray(); + if (netCoreProjectFile) + { + var relativeCsIncludes = + root.SelectNodes("/Project/ItemGroup/Compile/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); + + var explicitCsFiles = relativeCsIncludes. + Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). + Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))); + + var additionalCsFiles = System.IO.Directory.GetFiles(Directory, "*.cs", SearchOption.AllDirectories); + + csFiles = explicitCsFiles.Concat(additionalCsFiles).ToArray(); + + references = new string[0]; + } + else + { + + references = + root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); + + var relativeCsIncludes = + root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr). + NodeList(). + Select(node => node.Value). + ToArray(); + + csFiles = relativeCsIncludes. + Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs). + Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))). + ToArray(); + } } string[] references; diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs new file mode 100644 index 00000000000..6edd217af8d --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/DotNet.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; + +namespace Semmle.BuildAnalyser +{ + /// + /// Utilities to run the "dotnet" command. + /// + static class DotNet + { + public static int RestoreToDirectory(string projectOrSolutionFile, string packageDirectory) + { + using var proc = Process.Start("dotnet", $"restore --no-dependencies \"{projectOrSolutionFile}\" --packages \"{packageDirectory}\" /p:DisableImplicitNuGetFallbackFolder=true"); + proc.WaitForExit(); + return proc.ExitCode; + } + } +} diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs index 1f0755f307f..2ea3afb6c69 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/NugetPackages.cs @@ -1,10 +1,9 @@ -using System; +using Semmle.Util; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; namespace Semmle.BuildAnalyser { @@ -19,10 +18,10 @@ namespace Semmle.BuildAnalyser /// Create the package manager for a specified source tree. /// /// The source directory. - public NugetPackages(string sourceDir) + public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory) { SourceDirectory = sourceDir; - PackageDirectory = computeTempDirectory(sourceDir); + PackageDirectory = packageDirectory; // Expect nuget.exe to be in a `nuget` directory under the directory containing this exe. var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location; @@ -50,45 +49,12 @@ namespace Semmle.BuildAnalyser /// public IEnumerable PackageFiles => packages; - // Whether to delete the packages directory prior to each run. - // Makes each build more reproducible. - const bool cleanupPackages = true; - - public void Cleanup(IProgressMonitor pm) - { - var packagesDirectory = new DirectoryInfo(PackageDirectory); - - if (packagesDirectory.Exists) - { - try - { - packagesDirectory.Delete(true); - } - catch (System.IO.IOException ex) - { - pm.Warning(string.Format("Couldn't delete package directory - it's probably held open by something else: {0}", ex.Message)); - } - } - } - /// /// Download the packages to the temp folder. /// /// The progress monitor used for reporting errors etc. public void InstallPackages(IProgressMonitor pm) { - if (cleanupPackages) - { - Cleanup(pm); - } - - var packagesDirectory = new DirectoryInfo(PackageDirectory); - - if (!Directory.Exists(PackageDirectory)) - { - packagesDirectory.Create(); - } - foreach (var package in packages) { RestoreNugetPackage(package.FullName, pm); @@ -109,31 +75,7 @@ namespace Semmle.BuildAnalyser /// This will be in the Temp location /// so as to not trample the source tree. /// - public string PackageDirectory - { - get; - private set; - } - - readonly SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); - - /// - /// Computes a unique temp directory for the packages associated - /// with this source tree. Use a SHA1 of the directory name. - /// - /// - /// The full path of the temp directory. - string computeTempDirectory(string srcDir) - { - var bytes = Encoding.Unicode.GetBytes(srcDir); - - var sha = sha1.ComputeHash(bytes); - var sb = new StringBuilder(); - foreach (var b in sha.Take(8)) - sb.AppendFormat("{0:x2}", b); - - return Path.Combine(Path.GetTempPath(), "Semmle", "packages", sb.ToString()); - } + public TemporaryDirectory PackageDirectory { get; } /// /// Restore all files in a specified package. @@ -171,16 +113,15 @@ namespace Semmle.BuildAnalyser try { - using (var p = Process.Start(pi)) - { - string output = p.StandardOutput.ReadToEnd(); - string error = p.StandardError.ReadToEnd(); + using var p = Process.Start(pi); - p.WaitForExit(); - if (p.ExitCode != 0) - { - pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error); - } + string output = p.StandardOutput.ReadToEnd(); + string error = p.StandardError.ReadToEnd(); + + p.WaitForExit(); + if (p.ExitCode != 0) + { + pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error); } } catch (Exception ex) diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs index e0367fa63c1..106771faef2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Program.cs @@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Standalone /// /// Searches for source/references and creates separate extractions. /// - class Analysis + class Analysis : IDisposable { readonly ILogger logger; @@ -71,12 +71,9 @@ namespace Semmle.Extraction.CSharp.Standalone projectExtraction.Sources.AddRange(options.SolutionFile == null ? buildAnalysis.AllSourceFiles : buildAnalysis.ProjectSourceFiles); } - /// - /// Delete any Nuget assemblies. - /// - public void Cleanup() + public void Dispose() { - buildAnalysis.Cleanup(); + buildAnalysis.Dispose(); } }; @@ -85,8 +82,9 @@ namespace Semmle.Extraction.CSharp.Standalone static int Main(string[] args) { var options = Options.Create(args); + // options.CIL = true; // To do: Enable this var output = new ConsoleLogger(options.Verbosity); - var a = new Analysis(output); + using var a = new Analysis(output); if (options.Help) { @@ -97,6 +95,8 @@ namespace Semmle.Extraction.CSharp.Standalone if (options.Errors) return 1; + var start = DateTime.Now; + output.Log(Severity.Info, "Running C# standalone extractor"); a.AnalyseProjects(options); int sourceFiles = a.Extraction.Sources.Count(); @@ -117,10 +117,9 @@ namespace Semmle.Extraction.CSharp.Standalone new ExtractionProgress(output), new FileLogger(options.Verbosity, Extractor.GetCSharpLogPath()), options); - output.Log(Severity.Info, "Extraction complete"); + output.Log(Severity.Info, $"Extraction completed in {DateTime.Now-start}"); } - a.Cleanup(); return 0; } @@ -151,7 +150,7 @@ namespace Semmle.Extraction.CSharp.Standalone public void MissingSummary(int missingTypes, int missingNamespaces) { - logger.Log(Severity.Info, "Failed to resolve {0} types and {1} namespaces", missingTypes, missingNamespaces); + logger.Log(Severity.Info, "Failed to resolve {0} types in {1} namespaces", missingTypes, missingNamespaces); } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs index f4bde55ec55..5bbe1e3a5b2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/ProgressMonitor.cs @@ -1,4 +1,5 @@ using Semmle.Util.Logging; +using System; namespace Semmle.BuildAnalyser { @@ -9,15 +10,17 @@ namespace Semmle.BuildAnalyser { void FindingFiles(string dir); void UnresolvedReference(string id, string project); - void AnalysingProjectFiles(int count); + void AnalysingSolution(string filename); void FailedProjectFile(string filename, string reason); void FailedNugetCommand(string exe, string args, string message); void NugetInstall(string package); void ResolvedReference(string filename); - void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects); + void Summary(int existingSources, int usedSources, int missingSources, int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects, TimeSpan analysisTime); void Warning(string message); void ResolvedConflict(string asm1, string asm2); void MissingProject(string projectFile); + void CommandFailed(string exe, string arguments, int exitCode); + void MissingNuGet(); } class ProgressMonitor : IProgressMonitor @@ -46,9 +49,9 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Debug, "Unresolved {0} referenced by {1}", id, project); } - public void AnalysingProjectFiles(int count) + public void AnalysingSolution(string filename) { - logger.Log(Severity.Info, "Analyzing project files..."); + logger.Log(Severity.Info, $"Analyzing {filename}..."); } public void FailedProjectFile(string filename, string reason) @@ -73,7 +76,9 @@ namespace Semmle.BuildAnalyser } public void Summary(int existingSources, int usedSources, int missingSources, - int references, int unresolvedReferences, int resolvedConflicts, int totalProjects, int failedProjects) + int references, int unresolvedReferences, + int resolvedConflicts, int totalProjects, int failedProjects, + TimeSpan analysisTime) { logger.Log(Severity.Info, ""); logger.Log(Severity.Info, "Build analysis summary:"); @@ -85,6 +90,7 @@ namespace Semmle.BuildAnalyser logger.Log(Severity.Info, "{0, 6} resolved assembly conflicts", resolvedConflicts); logger.Log(Severity.Info, "{0, 6} projects", totalProjects); logger.Log(Severity.Info, "{0, 6} missing/failed projects", failedProjects); + logger.Log(Severity.Info, "Build analysis completed in {0}", analysisTime); } public void Warning(string message) @@ -94,12 +100,22 @@ namespace Semmle.BuildAnalyser public void ResolvedConflict(string asm1, string asm2) { - logger.Log(Severity.Info, "Resolved {0} as {1}", asm1, asm2); + logger.Log(Severity.Debug, "Resolved {0} as {1}", asm1, asm2); } public void MissingProject(string projectFile) { logger.Log(Severity.Info, "Solution is missing {0}", projectFile); } + + public void CommandFailed(string exe, string arguments, int exitCode) + { + logger.Log(Severity.Error, $"Command {exe} {arguments} failed with exit code {exitCode}"); + } + + public void MissingNuGet() + { + logger.Log(Severity.Error, "Missing nuget.exe"); + } } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj index 4cf0274b737..f9efd0d9ebb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/Semmle.Extraction.CSharp.Standalone.csproj @@ -1,4 +1,4 @@ - + Exe @@ -14,6 +14,7 @@ + diff --git a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs index b1a3edd4cf6..b4551dd8024 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp.Standalone/SolutionFile.cs @@ -12,6 +12,8 @@ namespace Semmle.BuildAnalyser { readonly Microsoft.Build.Construction.SolutionFile solutionFile; + private string FullPath { get; } + /// /// Read the file. /// @@ -19,8 +21,8 @@ namespace Semmle.BuildAnalyser public SolutionFile(string filename) { // SolutionFile.Parse() expects a rooted path. - var fullPath = Path.GetFullPath(filename); - solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(fullPath); + FullPath = Path.GetFullPath(filename); + solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(FullPath); } /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs index 98c021c8a6d..cc713b5ad2f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Accessor.cs @@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static Accessor Create(Context cx, IMethodSymbol symbol) => - AccessorFactory.Instance.CreateEntity(cx, symbol); + AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class AccessorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs index 298f838cfb9..a9baacbf728 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs @@ -104,7 +104,7 @@ namespace Semmle.Extraction.CSharp.Entities { case MethodKind.StaticConstructor: case MethodKind.Constructor: - return ConstructorFactory.Instance.CreateEntity(cx, constructor); + return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor); default: throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs index e365ca53ae0..98758fb773f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Conversion.cs @@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities : base(cx, init) { } public new static Conversion Create(Context cx, IMethodSymbol symbol) => - ConversionFactory.Instance.CreateEntity(cx, symbol); + ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol); public override Microsoft.CodeAnalysis.Location ReportingLocation { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs index 33f3a330f94..65557b16b67 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs @@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static Destructor Create(Context cx, IMethodSymbol symbol) => - DestructorFactory.Instance.CreateEntity(cx, symbol); + DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class DestructorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs index 224c81b9524..59f937a6331 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs @@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities TypeMention.Create(Context, syntaxType, this, type); } - public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol); + public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol); class EventFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs index 7dc0a4dfcff..da858b689dc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/EventAccessor.cs @@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities } public new static EventAccessor Create(Context cx, IMethodSymbol symbol) => - EventAccessorFactory.Instance.CreateEntity(cx, symbol); + EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class EventAccessorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs index 0488fe84ffe..6962e8381d9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Access.cs @@ -45,7 +45,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEntity target) : base(info.SetKind(AccessKind(info.Context, symbol))) { - cx.TrapWriter.Writer.expr_access(this, target); + if (!(target is null)) + { + cx.TrapWriter.Writer.expr_access(this, target); + } if (implicitThis && !symbol.IsStatic) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs index e41ef0edf23..0bc84ca9c0c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/MemberAccess.cs @@ -71,7 +71,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions if (symbol == null) { info.Context.ModelError(info.Node, "Failed to determine symbol for member access"); - return new MemberAccess(info.SetKind(ExprKind.UNKNOWN), expression, symbol); + // Default to property access - this can still give useful results but + // the target of the expression should be checked in QL. + return new MemberAccess(info.SetKind(ExprKind.PROPERTY_ACCESS), expression, symbol); } ExprKind kind; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs index 7ae4572cd7d..f126b7ff52f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs @@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities type = new Lazy(() => Entities.Type.Create(cx, symbol.GetAnnotatedType())); } - public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field); + public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field); // Do not populate backing fields. // Populate Tuple fields. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs index b9ece3d8c8e..af07c41dd6b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs @@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities TypeMention.Create(Context, syntax.Type, this, type); } - public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop); + public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop); public override void WriteId(TextWriter trapFile) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs index e570802ab3d..8b90f6905dd 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs @@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.Write('*'); } - public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field); + public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field); class LocalFunctionFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs index 6d0f14a014e..02d89d08a2f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs @@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities public static LocalVariable Create(Context cx, ISymbol local) { - return LocalVariableFactory.Instance.CreateEntity(cx, local); + return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local); } void DefineConstantValue(TextWriter trapFile) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 999903a1da8..7fe73cde06d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -129,7 +129,7 @@ namespace Semmle.Extraction.CSharp.Entities // Type arguments with different nullability can result in // a constructed method with different nullability of its parameters and return type, // so we need to create a distinct database entity for it. - trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); }); + trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, m.symbol); trapFile.Write((int)ta.Nullability); }); trapFile.Write('>'); } } @@ -199,12 +199,9 @@ namespace Semmle.Extraction.CSharp.Entities /// to make the reference to #3 in the label definition #4 for /// T valid. /// - protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type) + protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, ISymbol symbolBeingDefined) { - if (type.ContainsTypeParameters(cx, method)) - type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); - else - trapFile.WriteSubId(Type.Create(cx, type)); + type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g)); } protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) @@ -215,13 +212,13 @@ namespace Semmle.Extraction.CSharp.Entities if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, method); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type); + AddSignatureTypeToId(cx, trapFile, method, param.Type, method); switch (param.RefKind) { case RefKind.Out: @@ -244,9 +241,10 @@ namespace Semmle.Extraction.CSharp.Entities public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable explicitInterfaceImplementations) { - if (explicitInterfaceImplementations.Any()) + foreach (var i in explicitInterfaceImplementations) { - trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType))); + trapFile.Write(';'); + i.ContainingType.BuildNestedTypeId(cx, trapFile, null); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs index a0dd41aaafb..7a14bb719fc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/NamespaceDeclaration.cs @@ -23,7 +23,8 @@ namespace Semmle.Extraction.CSharp.Entities protected override void Populate(TextWriter trapFile) { - var ns = Namespace.Create(cx, (INamespaceSymbol)cx.GetModel(Node).GetSymbolInfo(Node.Name).Symbol); + var @namespace = (INamespaceSymbol) cx.GetModel(Node).GetSymbolInfo(Node.Name).Symbol; + var ns = Namespace.Create(cx, @namespace); trapFile.namespace_declarations(this, ns); trapFile.namespace_declaration_location(this, cx.Create(Node.Name.GetLocation())); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs index cb12918e72e..74e7de35a16 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/OrdinaryMethod.cs @@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities ExtractCompilerGenerated(trapFile); } - public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method); + public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method); class OrdinaryMethodFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index e5e2cc8ab26..05ff97db805 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -113,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities { bool isIndexer = prop.IsIndexer || prop.Parameters.Any(); - return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop); + return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop); } public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs index c4a79a7764b..9e211660344 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs @@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities trapFile.Write(";type"); } - public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol); + public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); class ArrayTypeFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs index f5b6bf36c44..bfaba1cff85 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/DynamicType.cs @@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities DynamicType(Context cx, IDynamicTypeSymbol init) : base(cx, init) { } - public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type); + public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index e22d32c0d01..20b7bf12ca8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities typeArgumentsLazy = new Lazy(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray()); } - public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type); + public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error; @@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities { if (symbol.TypeKind == TypeKind.Error) { - Context.Extractor.MissingType(symbol.ToString()); + Context.Extractor.MissingType(symbol.ToString(), Context.FromSource); return; } @@ -111,7 +111,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";type"); } @@ -177,7 +177,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(referencedType); + referencedType.symbol.BuildNestedTypeId(Context, trapFile, referencedType.symbol); trapFile.Write(";typeRef"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs index db8b5ff8c23..229666e6260 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/PointerType.cs @@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities public Type PointedAtType { get; private set; } - public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol); + public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); class PointerTypeFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index de6ea217084..ae9d3139a5c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities /// class TupleType : Type { - public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type); + public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type); class TupleTypeFactory : ICachedEntityFactory { @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 7d9f5e3651e..857d3def945 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -324,6 +324,14 @@ namespace Semmle.Extraction.CSharp.Entities } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; + + public override bool Equals(object obj) + { + var other = obj as Type; + return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol); + } + + public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol); } abstract class Type : Type where T : ITypeSymbol diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs index 2fdb8cd3a83..2c7c6373143 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs @@ -88,7 +88,7 @@ namespace Semmle.Extraction.CSharp.Entities } static public TypeParameter Create(Context cx, ITypeParameterSymbol p) => - TypeParameterFactory.Instance.CreateEntity(cx, p); + TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p); /// /// The variance of this type parameter. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 2a64a29fa0d..a66ae7cb1e8 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -51,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities public override void WriteId(TextWriter trapFile) { - AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type. + AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, symbol); // Needed for op_explicit(), which differs only by return type. trapFile.Write(' '); BuildMethodId(this, trapFile); } @@ -190,7 +190,7 @@ namespace Semmle.Extraction.CSharp.Entities return result; } - public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol); + public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol); class UserOperatorFactory : ICachedEntityFactory { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs index 4fdbe7c18ad..02b67efc164 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UsingDirective.cs @@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities if (namespaceSymbol == null) { - cx.Extractor.MissingNamespace(Node.Name.ToFullString()); + cx.Extractor.MissingNamespace(Node.Name.ToFullString(), cx.FromSource); cx.ModelError(Node, "Namespace not found"); return; } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index c2cb6a367eb..17a493771c6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -122,6 +122,24 @@ namespace Semmle.Extraction.CSharp } } + /// + /// Write the identifier for the symbol to the trapfile . + /// If any nested types are found in the identifier, then they are written out explicitly, without + /// prefixing the assembly ID. + /// + /// The type to write. + /// The extraction context. + /// The trap file to write to. + /// The outer symbol being defined (to avoid recursive ids). + public static void BuildNestedTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) + { + void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined) + { + symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType); + } + WriteType(cx, trapFile, type, symbolBeingDefined); + } + /// /// Constructs a unique string for this type symbol. /// @@ -130,10 +148,12 @@ namespace Semmle.Extraction.CSharp /// /// The extraction context. /// The trap builder used to store the result. + /// Whether to prefix the type ID with the assembly ID. + /// The outer symbol being defined (to avoid recursive ids). /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol symbolBeingDefined, Action subTermAction) { - if (type.SpecialType != SpecialType.None) + if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType)) { /* * Use the keyword ("int" etc) for the built-in types. @@ -150,7 +170,7 @@ namespace Semmle.Extraction.CSharp { case TypeKind.Array: var array = (IArrayTypeSymbol)type; - subTermAction(cx, trapFile, array.ElementType); + subTermAction(cx, trapFile, array.ElementType, symbolBeingDefined); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -160,15 +180,30 @@ namespace Semmle.Extraction.CSharp case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, subTermAction); + named.BuildNamedTypeId(cx, trapFile, prefix, symbolBeingDefined, subTermAction); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; - subTermAction(cx, trapFile, ptr.PointedAtType); + subTermAction(cx, trapFile, ptr.PointedAtType, symbolBeingDefined); trapFile.Write('*'); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; + if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbolBeingDefined)) + { + switch (tp.TypeParameterKind) + { + case TypeParameterKind.Method: + var method = Method.Create(cx, (IMethodSymbol)tp.ContainingSymbol); + trapFile.WriteSubId(method); + trapFile.Write('_'); + break; + case TypeParameterKind.Type: + subTermAction(cx, trapFile, tp.ContainingType, symbolBeingDefined); + trapFile.Write('_'); + break; + } + } trapFile.Write(tp.Name); return; case TypeKind.Dynamic: @@ -211,10 +246,8 @@ namespace Semmle.Extraction.CSharp trapFile.Write("::"); } - static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) + static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, bool prefixAssembly, ISymbol symbolBeingDefined, Action subTermAction) { - bool prefixAssembly = true; - if (cx.Extractor.Standalone) prefixAssembly = false; if (named.ContainingAssembly is null) prefixAssembly = false; if (named.IsTupleType) @@ -225,7 +258,7 @@ namespace Semmle.Extraction.CSharp { trapFile.Write(f.Name); trapFile.Write(":"); - subTermAction(cx, tb0, f.Type); + subTermAction(cx, tb0, f.Type, symbolBeingDefined); } ); trapFile.Write(")"); @@ -234,7 +267,7 @@ namespace Semmle.Extraction.CSharp if (named.ContainingType != null) { - subTermAction(cx, trapFile, named.ContainingType); + subTermAction(cx, trapFile, named.ContainingType, symbolBeingDefined); trapFile.Write('.'); } else if (named.ContainingNamespace != null) @@ -256,14 +289,14 @@ namespace Semmle.Extraction.CSharp } else { - subTermAction(cx, trapFile, named.ConstructedFrom); + subTermAction(cx, trapFile, named.ConstructedFrom, symbolBeingDefined); trapFile.Write('<'); // Encode the nullability of the type arguments in the label. // Type arguments with different nullability can result in // a constructed type with different nullability of its members and methods, // so we need to create a distinct database entity for it. trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), - (ta, tb0) => subTermAction(cx, tb0, ta.Symbol) + (ta, tb0) => subTermAction(cx, tb0, ta.Symbol, symbolBeingDefined) ); trapFile.Write('>'); } @@ -275,16 +308,16 @@ namespace Semmle.Extraction.CSharp trapFile.Write('.'); } - static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) + static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) { var buildParam = includeParamName ? (prop, tb0) => { tb0.Write(prop.Name); tb0.Write(' '); - subTermAction(cx, tb0, prop.Type); + subTermAction(cx, tb0, prop.Type, null); } - : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type)); + : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type, null)); int memberCount = type.GetMembers().OfType().Count(); int hackTypeNumber = memberCount == 1 ? 1 : 0; trapFile.Write("<>__AnonType"); @@ -356,7 +389,7 @@ namespace Semmle.Extraction.CSharp if (namedType.IsAnonymousType) { - namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false); + namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub, _) => sub.BuildDisplayName(cx0, tb0), false); } trapFile.Write(namedType.Name); diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 93f99381858..96024f044d0 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -51,7 +51,20 @@ namespace Semmle.Extraction /// The new/existing entity. public Entity CreateEntity(ICachedEntityFactory factory, Type init) where Entity : ICachedEntity { - return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init); + return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, objectEntityCache); + } + + /// + /// Creates a new entity using the factory. + /// + /// The entity factory. + /// The initializer for the entity. + /// The new/existing entity. + public Entity CreateEntityFromSymbol(ICachedEntityFactory factory, Type init) + where Entity : ICachedEntity + where Type: ISymbol + { + return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, symbolEntityCache); } // A recursion guard against writing to the trap file whilst writing an id to the trap file. @@ -136,8 +149,13 @@ namespace Semmle.Extraction public Label GetNewLabel() => new Label(GetNewId()); private Entity CreateNonNullEntity(ICachedEntityFactory factory, Type init) where Entity : ICachedEntity + => CreateNonNullEntity(factory, init, objectEntityCache); + + private Entity CreateNonNullEntity(ICachedEntityFactory factory, Type init, IDictionary dictionary) + where Entity : ICachedEntity + where Type : Src { - if (objectEntityCache.TryGetValue(init, out var cached)) + if (dictionary.TryGetValue(init, out var cached)) return (Entity)cached; using (StackGuard) @@ -146,7 +164,7 @@ namespace Semmle.Extraction var entity = factory.Create(this, init); entity.Label = label; - objectEntityCache[init] = entity; + dictionary[init] = entity; DefineLabel(entity, TrapWriter.Writer, Extractor); if (entity.NeedsPopulation) @@ -155,7 +173,7 @@ namespace Semmle.Extraction #if DEBUG_LABELS using (var id = new StringWriter()) { - entity.WriteId(id); + entity.WriteQuotedId(id); CheckEntityHasUniqueLabel(id.ToString(), entity); } #endif @@ -200,7 +218,9 @@ namespace Semmle.Extraction #if DEBUG_LABELS readonly Dictionary idLabelCache = new Dictionary(); #endif - readonly Dictionary objectEntityCache = new Dictionary(); + + readonly IDictionary objectEntityCache = new Dictionary(); + readonly IDictionary symbolEntityCache = new Dictionary(10000, SymbolEqualityComparer.IncludeNullability); readonly Dictionary entityLabelCache = new Dictionary(); readonly HashSet - public static string FindProgramOnPath(string prog) + public static string? FindProgramOnPath(string prog) { var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator); string[] exes; diff --git a/csharp/extractor/Semmle.Util/FuzzyDictionary.cs b/csharp/extractor/Semmle.Util/FuzzyDictionary.cs index a00d75fbbe5..6f364904b06 100644 --- a/csharp/extractor/Semmle.Util/FuzzyDictionary.cs +++ b/csharp/extractor/Semmle.Util/FuzzyDictionary.cs @@ -37,7 +37,7 @@ namespace Semmle.Util /// /// /// The value type. - public class FuzzyDictionary + public class FuzzyDictionary where T:class { // All data items indexed by the "base string" (stripped of numbers) readonly Dictionary>> index = new Dictionary>>(); @@ -61,7 +61,7 @@ namespace Semmle.Util /// Vector 1 /// Vector 2 /// The Hamming Distance. - static int HammingDistance(IEnumerable v1, IEnumerable v2) + static int HammingDistance(IEnumerable v1, IEnumerable v2) where U: notnull { return v1.Zip(v2, (x, y) => x.Equals(y) ? 0 : 1).Sum(); } @@ -72,11 +72,10 @@ namespace Semmle.Util /// The query string. /// The distance between the query string and the stored string. /// The best match, or null (default). - public T FindMatch(string query, out int distance) + public T? FindMatch(string query, out int distance) { string root = StripDigits(query); - List> list; - if (!index.TryGetValue(root, out list)) + if (!index.TryGetValue(root, out var list)) { distance = 0; return default(T); @@ -93,9 +92,9 @@ namespace Semmle.Util /// The distance function. /// The distance between the query and the stored string. /// The stored value. - static T BestMatch(string query, IEnumerable> candidates, Func distance, out int bestDistance) + static T? BestMatch(string query, IEnumerable> candidates, Func distance, out int bestDistance) { - T bestMatch = default(T); + T? bestMatch = default(T); bestDistance = 0; bool first = true; diff --git a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs index d53fcf99ff4..7665dedfa70 100644 --- a/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs +++ b/csharp/extractor/Semmle.Util/IEnumerableExtensions.cs @@ -93,7 +93,7 @@ namespace Semmle.Util /// The type of the item. /// The list of items to hash. /// The hash code. - public static int SequenceHash(this IEnumerable items) + public static int SequenceHash(this IEnumerable items) where T: notnull { int h = 0; foreach (var i in items) diff --git a/csharp/extractor/Semmle.Util/LineCounter.cs b/csharp/extractor/Semmle.Util/LineCounter.cs index c122d5865be..f4f6758a250 100644 --- a/csharp/extractor/Semmle.Util/LineCounter.cs +++ b/csharp/extractor/Semmle.Util/LineCounter.cs @@ -31,9 +31,9 @@ namespace Semmle.Util //#################### PUBLIC METHODS #################### #region - public override bool Equals(Object other) + public override bool Equals(object? other) { - LineCounts rhs = other as LineCounts; + var rhs = other as LineCounts; return rhs != null && Total == rhs.Total && Code == rhs.Code && Comment == rhs.Comment; } diff --git a/csharp/extractor/Semmle.Util/Logger.cs b/csharp/extractor/Semmle.Util/Logger.cs index d6405724734..cd353bd4f0f 100644 --- a/csharp/extractor/Semmle.Util/Logger.cs +++ b/csharp/extractor/Semmle.Util/Logger.cs @@ -67,8 +67,8 @@ namespace Semmle.Util.Logging try { - var dir = Path.GetDirectoryName(outputFile); - if (dir.Length > 0 && !System.IO.Directory.Exists(dir)) + string? dir = Path.GetDirectoryName(outputFile); + if (!string.IsNullOrEmpty(dir) && !System.IO.Directory.Exists(dir)) Directory.CreateDirectory(dir); writer = new PidStreamWriter(new FileStream(outputFile, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, 8192)); diff --git a/csharp/extractor/Semmle.Util/LoggerUtils.cs b/csharp/extractor/Semmle.Util/LoggerUtils.cs index 39a40c37158..d94ff6f189f 100644 --- a/csharp/extractor/Semmle.Util/LoggerUtils.cs +++ b/csharp/extractor/Semmle.Util/LoggerUtils.cs @@ -21,7 +21,7 @@ namespace Semmle.Util private readonly string prefix = "[" + Process.GetCurrentProcess().Id + "] "; - public override void WriteLine(string value) + public override void WriteLine(string? value) { lock (mutex) { @@ -29,9 +29,9 @@ namespace Semmle.Util } } - public override void WriteLine(string value, object[] args) + public override void WriteLine(string? value, object?[] args) { - WriteLine(String.Format(value, args)); + WriteLine(value is null ? value : String.Format(value, args)); } readonly object mutex = new object(); diff --git a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs index 0d9d6b04a13..5252372a58b 100644 --- a/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs +++ b/csharp/extractor/Semmle.Util/ProcessStartInfoExtensions.cs @@ -14,7 +14,7 @@ namespace Semmle.Util stdout = new List(); using (var process = Process.Start(pi)) { - string s; + string? s; do { s = process.StandardOutput.ReadLine(); diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index 4ef3eda35d9..39f0c7cdedb 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -6,6 +6,7 @@ Semmle.Util false win-x64;linux-x64;osx-x64 + enable diff --git a/csharp/extractor/Semmle.Util/SharedReference.cs b/csharp/extractor/Semmle.Util/SharedReference.cs index 6870c5acb35..ba87caeefaa 100644 --- a/csharp/extractor/Semmle.Util/SharedReference.cs +++ b/csharp/extractor/Semmle.Util/SharedReference.cs @@ -13,6 +13,6 @@ namespace Semmle.Util /// /// The shared object to which different parts of the code want to refer. /// - public T Obj { get; set; } + public T? Obj { get; set; } } } diff --git a/csharp/extractor/Semmle.Util/TemporaryDirectory.cs b/csharp/extractor/Semmle.Util/TemporaryDirectory.cs new file mode 100644 index 00000000000..a155372c9d8 --- /dev/null +++ b/csharp/extractor/Semmle.Util/TemporaryDirectory.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; + +namespace Semmle.Util +{ + /// + /// A temporary directory that is created within the system temp directory. + /// When this object is disposed, the directory is deleted. + /// + public sealed class TemporaryDirectory : IDisposable + { + public DirectoryInfo DirInfo { get; } + + public TemporaryDirectory(string name) + { + DirInfo = new DirectoryInfo(name); + DirInfo.Create(); + } + + public void Dispose() + { + DirInfo.Delete(true); + } + + public override string ToString() => DirInfo.FullName.ToString(); + } +} diff --git a/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql b/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql index 6b9acf69e3c..ac9a3d90dbd 100644 --- a/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql +++ b/csharp/ql/src/Security Features/CWE-091/XMLInjection.ql @@ -11,7 +11,7 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Xml /** diff --git a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql index 2b87d61f193..0aab5e3181a 100644 --- a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql +++ b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.ql @@ -12,7 +12,7 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.commons.Util /** diff --git a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql index 1b42ea7399d..3b9d6af7d14 100644 --- a/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql +++ b/csharp/ql/src/Security Features/CWE-134/UncontrolledFormatString.ql @@ -11,8 +11,8 @@ */ import csharp -import semmle.code.csharp.dataflow.flowsources.Remote -import semmle.code.csharp.dataflow.flowsources.Local +import semmle.code.csharp.security.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.dataflow.TaintTracking import semmle.code.csharp.frameworks.Format import DataFlow::PathGraph diff --git a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql index 4419a4f1312..b8b18c6b56d 100644 --- a/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql +++ b/csharp/ql/src/Security Features/CWE-201/ExposureInTransmittedData.ql @@ -11,8 +11,7 @@ import csharp import semmle.code.csharp.security.SensitiveActions -import semmle.code.csharp.security.dataflow.XSS -import semmle.code.csharp.security.dataflow.Email +import semmle.code.csharp.security.dataflow.flowsinks.Remote import semmle.code.csharp.frameworks.system.data.Common import semmle.code.csharp.frameworks.System import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph @@ -42,11 +41,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { - sink instanceof XSS::Sink - or - sink instanceof Email::Sink - } + override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink } } from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql index 8cebb2601c4..d9db652c8d8 100644 --- a/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql +++ b/csharp/ql/src/Security Features/CWE-209/ExceptionInformationExposure.ql @@ -14,7 +14,7 @@ import csharp import semmle.code.csharp.frameworks.System -import semmle.code.csharp.security.dataflow.XSS +import semmle.code.csharp.security.dataflow.flowsinks.Remote import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph /** @@ -46,7 +46,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { sink instanceof XSS::Sink } + override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink } override predicate isSanitizer(DataFlow::Node sanitizer) { // Do not flow through Message diff --git a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql index 88a5c3da4ed..88a0b970a7a 100644 --- a/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql +++ b/csharp/ql/src/Security Features/CWE-838/InappropriateEncoding.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.UI import semmle.code.csharp.security.dataflow.SqlInjection -import semmle.code.csharp.security.dataflow.XSS +import semmle.code.csharp.security.dataflow.flowsinks.Html import semmle.code.csharp.security.dataflow.UrlRedirect import semmle.code.csharp.security.Sanitizers import semmle.code.csharp.dataflow.DataFlow2::DataFlow2 @@ -114,7 +114,7 @@ module EncodingConfigurations { override string getKind() { result = "HTML expression" } - override predicate requiresEncoding(Node n) { n instanceof XSS::HtmlSink } + override predicate requiresEncoding(Node n) { n instanceof HtmlSink } override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr } } diff --git a/csharp/ql/src/Security Features/InsecureRandomness.ql b/csharp/ql/src/Security Features/InsecureRandomness.ql index bd16dda8816..ef1665819f7 100644 --- a/csharp/ql/src/Security Features/InsecureRandomness.ql +++ b/csharp/ql/src/Security Features/InsecureRandomness.ql @@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.Test import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph module Random { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.security.SensitiveActions /** diff --git a/csharp/ql/src/codeql-suites/csharp-code-scanning.qls b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls new file mode 100644 index 00000000000..3646204da7d --- /dev/null +++ b/csharp/ql/src/codeql-suites/csharp-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for C# +- qlpack: codeql-csharp +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index df14eec51a7..6bb4774c070 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-csharp version: 0.0.0 dbscheme: semmlecode.csharp.dbscheme suites: codeql-suites +extractor: csharp diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll index 87eee2a80be..26b6e5f7b96 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/LibraryTypeDataFlow.qll @@ -755,6 +755,11 @@ class IEnumerableFlow extends LibraryTypeDataFlow { sink = TCallableFlowSinkReturn() ) or + name = "AsQueryable" and + arity = 1 and + source = TCallableFlowSourceArg(0) and + sink = TCallableFlowSinkReturn() + or name = "Average" and ( arity = 2 and diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll index 07dc38d320d..cf69f54717a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/PublicCallableParameter.qll @@ -1,9 +1,10 @@ /** + * DEPRECATED. + * * Provides classes representing data flow sources for parameters of public callables. */ import csharp -private import semmle.code.csharp.frameworks.WCF /** * A parameter of a public callable, for example `p` in diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll index f8240583108..07a23b36c26 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Remote.qll @@ -1,218 +1,7 @@ /** - * Provides classes representing data flow sources for remote user input. + * DEPRECATED. + * + * Use `semmle.code.csharp.security.dataflow.flowsources.Remote` instead. */ -import csharp -private import semmle.code.csharp.frameworks.system.Net -private import semmle.code.csharp.frameworks.system.Web -private import semmle.code.csharp.frameworks.system.web.Http -private import semmle.code.csharp.frameworks.system.web.Mvc -private import semmle.code.csharp.frameworks.system.web.Services -private import semmle.code.csharp.frameworks.system.web.ui.WebControls -private import semmle.code.csharp.frameworks.WCF -private import semmle.code.csharp.frameworks.microsoft.Owin -private import semmle.code.csharp.frameworks.microsoft.AspNetCore - -/** A data flow source of remote user input. */ -abstract class RemoteFlowSource extends DataFlow::Node { - /** Gets a string that describes the type of this remote flow source. */ - abstract string getSourceType(); -} - -/** A data flow source of remote user input (ASP.NET). */ -abstract class AspNetRemoteFlowSource extends RemoteFlowSource { } - -/** A member containing an ASP.NET query string. */ -class AspNetQueryStringMember extends Member { - AspNetQueryStringMember() { - exists(RefType t | - t instanceof SystemWebHttpRequestClass or - t instanceof SystemNetHttpListenerRequestClass or - t instanceof SystemWebHttpRequestBaseClass - | - this = t.getProperty(getHttpRequestFlowPropertyNames()) or - this.(Field).getType() = t or - this.(Property).getType() = t or - this.(Callable).getReturnType() = t - ) - } -} - -/** - * Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the - * request. - */ -private string getHttpRequestFlowPropertyNames() { - result = "QueryString" or - result = "Headers" or - result = "RawUrl" or - result = "Url" or - result = "Cookies" or - result = "Form" or - result = "Params" or - result = "Path" or - result = "PathInfo" -} - -/** A data flow source of remote user input (ASP.NET query string). */ -class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetQueryStringRemoteFlowSource() { - exists(RefType t | - t instanceof SystemWebHttpRequestClass or - t instanceof SystemNetHttpListenerRequestClass or - t instanceof SystemWebHttpRequestBaseClass - | - // A request object can be indexed, so taint the object as well - this.getExpr().getType() = t - ) - or - this.getExpr() = any(AspNetQueryStringMember m).getAnAccess() - } - - override string getSourceType() { result = "ASP.NET query string" } -} - -/** A data flow source of remote user input (ASP.NET unvalidated request data). */ -class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, - DataFlow::ExprNode { - AspNetUnvalidatedQueryStringRemoteFlowSource() { - this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or - this.getExpr() = - any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall() - } - - override string getSourceType() { result = "ASP.NET unvalidated request data" } -} - -/** A data flow source of remote user input (ASP.NET user input). */ -class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { - AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } - - override string getSourceType() { result = "ASP.NET user input" } -} - -/** A data flow source of remote user input (WCF based web service). */ -class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { - WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) } - - override string getSourceType() { result = "web service input" } -} - -/** A data flow source of remote user input (ASP.NET web service). */ -class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { - AspNetServiceRemoteFlowSource() { - exists(Method m | - m.getAParameter() = this.getParameter() and - m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass - ) - } - - override string getSourceType() { result = "ASP.NET web service input" } -} - -/** A data flow source of remote user input (ASP.NET request message). */ -class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - SystemNetHttpRequestMessageRemoteFlowSource() { - getType() instanceof SystemWebHttpRequestMessageClass - } - - override string getSourceType() { result = "ASP.NET request message" } -} - -/** - * A data flow source of remote user input (Microsoft Owin, a query, request, - * or path string). - */ -class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - MicrosoftOwinStringFlowSource() { - this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall() - } - - override string getSourceType() { result = "Microsoft Owin request or query string" } -} - -/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ -class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { - MicrosoftOwinRequestRemoteFlowSource() { - exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | - this.getExpr() = p.getGetter().getACall() - | - p = owinRequest.getAcceptProperty() or - p = owinRequest.getBodyProperty() or - p = owinRequest.getCacheControlProperty() or - p = owinRequest.getContentTypeProperty() or - p = owinRequest.getContextProperty() or - p = owinRequest.getCookiesProperty() or - p = owinRequest.getHeadersProperty() or - p = owinRequest.getHostProperty() or - p = owinRequest.getMediaTypeProperty() or - p = owinRequest.getMethodProperty() or - p = owinRequest.getPathProperty() or - p = owinRequest.getPathBaseProperty() or - p = owinRequest.getQueryProperty() or - p = owinRequest.getQueryStringProperty() or - p = owinRequest.getRemoteIpAddressProperty() or - p = owinRequest.getSchemeProperty() or - p = owinRequest.getURIProperty() - ) - } - - override string getSourceType() { result = "Microsoft Owin request" } -} - -/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ -class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { - ActionMethodParameter() { - exists(Parameter p | - p = this.getParameter() and - p.fromSource() - | - p = any(Controller c).getAnActionMethod().getAParameter() or - p = any(ApiController c).getAnActionMethod().getAParameter() - ) - } - - override string getSourceType() { result = "ASP.NET MVC action method parameter" } -} - -/** A data flow source of remote user input (ASP.NET Core). */ -abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } - -/** A data flow source of remote user input (ASP.NET query collection). */ -class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { - AspNetCoreQueryRemoteFlowSource() { - exists(ValueOrRefType t | - t instanceof MicrosoftAspNetCoreHttpHttpRequest or - t instanceof MicrosoftAspNetCoreHttpQueryCollection or - t instanceof MicrosoftAspNetCoreHttpQueryString - | - this.getExpr().(Call).getTarget().getDeclaringType() = t or - this.asExpr().(Access).getTarget().getDeclaringType() = t - ) - or - exists(Call c | - c - .getTarget() - .getDeclaringType() - .hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and - c.getTarget().getName() = "TryGetValue" and - this.asExpr() = c.getArgumentForName("value") - ) - } - - override string getSourceType() { result = "ASP.NET Core query string" } -} - -/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ -class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { - AspNetCoreActionMethodParameter() { - exists(Parameter p | - p = this.getParameter() and - p.fromSource() - | - p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() - ) - } - - override string getSourceType() { result = "ASP.NET Core MVC action method parameter" } -} +import semmle.code.csharp.security.dataflow.flowsources.Remote diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 7d2d728b67e..a1daeb66411 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 7d2d728b67e..a1daeb66411 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 7d2d728b67e..a1daeb66411 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 7d2d728b67e..a1daeb66411 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 7d2d728b67e..a1daeb66411 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..0dc3b8eff45 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,175 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 22684e34b48..4a6693fbebf 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1499,3 +1499,12 @@ private predicate viableConstantBooleanParamArg( } int accessPathLimit() { result = 3 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { none() } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll index c0d75bfd9fe..d1e1017e0d1 100644 --- a/csharp/ql/src/semmle/code/csharp/exprs/Access.qll +++ b/csharp/ql/src/semmle/code/csharp/exprs/Access.qll @@ -388,7 +388,12 @@ library class PropertyAccessExpr extends Expr, @property_access_expr { /** Gets the target of this property access. */ Property getProperty() { expr_access(this, result) } - override string toString() { result = "access to property " + this.getProperty().getName() } + override string toString() { + result = "access to property " + this.getProperty().getName() + or + not exists(this.getProperty()) and + result = "access to property (unknown)" + } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 833c929ecc5..9a75ca19154 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -12,7 +12,9 @@ private newtype TIRType = TIRBooleanType(int byteSize) { Language::hasBooleanType(byteSize) } or TIRSignedIntegerType(int byteSize) { Language::hasSignedIntegerType(byteSize) } or TIRUnsignedIntegerType(int byteSize) { Language::hasUnsignedIntegerType(byteSize) } or - TIRFloatingPointType(int byteSize) { Language::hasFloatingPointType(byteSize) } or + TIRFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + Language::hasFloatingPointType(byteSize, base, domain) + } or TIRAddressType(int byteSize) { Language::hasAddressType(byteSize) } or TIRFunctionAddressType(int byteSize) { Language::hasFunctionAddressType(byteSize) } or TIROpaqueType(Language::OpaqueTypeTag tag, int byteSize) { @@ -104,7 +106,7 @@ private class IRSizedType extends IRType { this = TIRBooleanType(byteSize) or this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) or + this = TIRFloatingPointType(byteSize, _, _) or this = TIRAddressType(byteSize) or this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) @@ -133,7 +135,7 @@ class IRNumericType extends IRSizedType { IRNumericType() { this = TIRSignedIntegerType(byteSize) or this = TIRUnsignedIntegerType(byteSize) or - this = TIRFloatingPointType(byteSize) + this = TIRFloatingPointType(byteSize, _, _) } } @@ -171,14 +173,43 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { * A floating-point type. */ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { - final override string toString() { result = "float" + byteSize.toString() } + final private int base; + final private Language::TypeDomain domain; + + IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) } + + final override string toString() { + result = getDomainPrefix() + getBaseString() + byteSize.toString() + } final override Language::LanguageType getCanonicalLanguageType() { - result = Language::getCanonicalFloatingPointType(byteSize) + result = Language::getCanonicalFloatingPointType(byteSize, base, domain) } pragma[noinline] final override int getByteSize() { result = byteSize } + + /** Gets the numeric base of the type. Can be either 2 (binary) or 10 (decimal). */ + final int getBase() { result = base } + + /** + * Gets the type domain of the type. Can be `RealDomain`, `ComplexDomain`, or `ImaginaryDomain`. + */ + final Language::TypeDomain getDomain() { result = domain } + + private string getBaseString() { + base = 2 and result = "float" + or + base = 10 and result = "decimal" + } + + private string getDomainPrefix() { + domain instanceof Language::RealDomain and result = "" + or + domain instanceof Language::ComplexDomain and result = "c" + or + domain instanceof Language::ImaginaryDomain and result = "i" + } } /** diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index fc9d0758125..38216872f2b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll index 94d0192fe18..edf4bc00259 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRSanity.qll @@ -149,6 +149,26 @@ module InstructionSanity { count(instr.getBlock().getAPredecessor()) < 2 } + /** + * Holds if a memory operand is connected to a definition with an unmodeled result, other than + * `UnmodeledDefinition` itself. + */ + query predicate memoryOperandDefinitionIsUnmodeled( + Instruction instr, string message, IRFunction func, string funcText + ) { + exists(MemoryOperand operand, Instruction def | + operand = instr.getAnOperand() and + not operand instanceof UnmodeledUseOperand and + def = operand.getAnyDef() and + not def.isResultModeled() and + not def instanceof UnmodeledDefinitionInstruction and + message = + "Memory operand definition has unmodeled result, but is not the `UnmodeledDefinition` instruction in function '$@'" and + func = instr.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + ) + } + /** * Holds if operand `operand` consumes a value that was defined in * a different function. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index fc9d0758125..38216872f2b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -525,7 +525,7 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } -class ReturnIndirectionInstruction extends Instruction { +class ReturnIndirectionInstruction extends VariableInstruction { ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } @@ -535,6 +535,12 @@ class ReturnIndirectionInstruction extends Instruction { final AddressOperand getSourceAddressOperand() { result = getAnOperand() } final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } + + /** + * Gets the parameter for which this instruction reads the final pointed-to value within the + * function. + */ + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } } class CopyInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll new file mode 100644 index 00000000000..a7fb1b3c07e --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/PrintValueNumbering.qll @@ -0,0 +1,17 @@ +private import internal.ValueNumberingImports +private import ValueNumbering + +/** + * Provides additional information about value numbering in IR dumps. + */ +class ValueNumberPropertyProvider extends IRPropertyProvider { + override string getInstructionProperty(Instruction instr, string key) { + exists(ValueNumber vn | + vn = valueNumber(instr) and + key = "valnum" and + if strictcount(vn.getAnInstruction()) > 1 + then result = vn.getDebugString() + else result = "unique" + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll index 161f69936e9..13d19587135 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll @@ -1,21 +1,6 @@ private import internal.ValueNumberingInternal private import internal.ValueNumberingImports -/** - * Provides additional information about value numbering in IR dumps. - */ -class ValueNumberPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instr, string key) { - exists(ValueNumber vn | - vn = valueNumber(instr) and - key = "valnum" and - if strictcount(vn.getAnInstruction()) > 1 - then result = vn.getDebugString() - else result = "unique" - ) - } -} - /** * The value number assigned to a particular set of instructions that produce equivalent results. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll index dc02760c7c4..72bb239c153 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/PrintSSA.qll @@ -6,11 +6,12 @@ private import DebugSSA bindingset[offset] private string getKeySuffixForOffset(int offset) { + offset >= 0 and if offset % 2 = 0 then result = "" else result = "_Chi" } bindingset[offset] -private int getIndexForOffset(int offset) { result = offset / 2 } +private int getIndexForOffset(int offset) { offset >= 0 and result = offset / 2 } /** * Property provide that dumps the memory access of each result. Useful for debugging SSA diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll index cffe3d09f39..fdd7ef804d2 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll @@ -61,9 +61,13 @@ predicate hasUnsignedIntegerType(int byteSize) { } /** - * Holds if an `IRFloatingPointType` with the specified `byteSize` should exist. + * Holds if an `IRFloatingPointType` with the specified size, base, and type domain should exist. */ -predicate hasFloatingPointType(int byteSize) { byteSize = any(FloatingPointType type).getSize() } +predicate hasFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + byteSize = any(FloatingPointType type).getSize() and + base = 2 and + domain instanceof Language::RealDomain +} private predicate isPointerIshType(Type type) { type instanceof PointerType or @@ -314,9 +318,11 @@ CSharpPRValueType getCanonicalUnsignedIntegerType(int byteSize) { /** * Gets the `CSharpType` that is the canonical type for an `IRFloatingPointType` with the specified - * `byteSize`. + * size, base, and type domain. */ -CSharpPRValueType getCanonicalFloatingPointType(int byteSize) { +CSharpPRValueType getCanonicalFloatingPointType(int byteSize, int base, Language::TypeDomain domain) { + base = 2 and + domain instanceof Language::RealDomain and result = TPRValueType(any(FloatingPointType type | type.getSize() = byteSize)) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll index a8fb448f8d0..2272257fb19 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/IRCSharpLanguage.qll @@ -28,6 +28,44 @@ class IntegralType = CSharp::IntegralType; class FloatingPointType = CSharp::FloatingPointType; +private newtype TTypeDomain = TRealDomain() + +/** + * The type domain of a floating-point type. One of `RealDomain`, `ComplexDomain`, or + * `ImaginaryDomain`. + */ +class TypeDomain extends TTypeDomain { + /** Gets a textual representation of this type domain. */ + string toString() { none() } +} + +/** + * The type domain of a floating-point type that represents a real number. + */ +class RealDomain extends TypeDomain, TRealDomain { + final override string toString() { result = "real" } +} + +/** + * The type domain of a floating-point type that represents a complex number. Not currently used in + * C#. + */ +class ComplexDomain extends TypeDomain { + ComplexDomain() { none() } + + final override string toString() { result = "complex" } +} + +/** + * The type domain of a floating-point type that represents an imaginary number. Not currently used + * in C#. + */ +class ImaginaryDomain extends TypeDomain { + ImaginaryDomain() { none() } + + final override string toString() { result = "imaginary" } +} + private newtype TClassDerivation = // Note that this is the `Class` type exported from this module, not CSharp::Class. MkClassDerivation(Class base, Class derived) { derived.getABaseType() = base } diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll index 8eff8c88e3f..a0ce6d9d1ae 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CleartextStorage.qll @@ -5,10 +5,10 @@ import csharp module CleartextStorage { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.security.SensitiveActions - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink /** * A data flow source for cleartext storage of sensitive information. diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll index 3c168463d9d..d58d851b7c8 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CodeInjection.qll @@ -5,8 +5,8 @@ import csharp module CodeInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.system.codedom.Compiler import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll index 01d6c01fd2b..7d2a49784e1 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/CommandInjection.qll @@ -5,7 +5,7 @@ import csharp module CommandInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Diagnostics import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll index 18c725d273e..0694b27f985 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ConditionalBypass.qll @@ -8,7 +8,7 @@ import csharp module UserControlledBypassOfSensitiveMethod { import semmle.code.csharp.controlflow.Guards import semmle.code.csharp.controlflow.BasicBlocks - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.security.SensitiveActions diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll index 45d5794dca6..19866738341 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ExposureOfPrivateInformation.qll @@ -5,8 +5,8 @@ import csharp module ExposureOfPrivateInformation { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink import semmle.code.csharp.security.PrivateData /** diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll index 329e001236f..50681f9721c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LDAPInjection.qll @@ -6,7 +6,7 @@ import csharp module LDAPInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.DirectoryServices import semmle.code.csharp.frameworks.system.directoryservices.Protocols import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll index 3460362cf99..400b1ac8763 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/LogForging.qll @@ -5,11 +5,11 @@ import csharp module LogForging { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers - import semmle.code.csharp.security.sinks.ExternalLocationSink + import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink /** * A data flow source for untrusted user input used in log entries. diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll index 28b8350a200..ba5ee7147d3 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/MissingXMLValidation.qll @@ -6,7 +6,7 @@ import csharp module MissingXMLValidation { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.Xml import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll index bb40b62a0be..28c5c79e0af 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ReDoS.qll @@ -7,7 +7,7 @@ import csharp module ReDoS { private import semmle.code.csharp.dataflow.DataFlow2 - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll index 51f8605c1af..2edfbc4ab7c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/RegexInjection.qll @@ -6,7 +6,7 @@ import csharp module RegexInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll index 6ae49c6f7d5..236fe62aa2c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/ResourceInjection.qll @@ -5,8 +5,8 @@ import csharp module ResourceInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.system.Data import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll index cb393e00179..21c2628aa62 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/SqlInjection.qll @@ -5,8 +5,8 @@ import csharp module SqlInjection { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.dataflow.flowsources.Local + import semmle.code.csharp.security.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Local import semmle.code.csharp.frameworks.Sql import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll index 78a0ca2c3bf..df59f0a4793 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll @@ -7,7 +7,7 @@ import csharp module TaintedPath { import semmle.code.csharp.controlflow.Guards - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.IO import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 57b3a78485b..0943774d8cd 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,7 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.dataflow.flowsources.Remote + private import semmle.code.csharp.security.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers /** diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll index ff501a1c096..2008e62c60d 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UrlRedirect.qll @@ -5,7 +5,7 @@ import csharp module UrlRedirect { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.controlflow.Guards import semmle.code.csharp.frameworks.system.Web import semmle.code.csharp.frameworks.system.web.Mvc diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll index 67c5cb552f5..425fd6b4019 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XMLEntityInjection.qll @@ -5,7 +5,7 @@ import csharp module XMLEntityInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.System import semmle.code.csharp.frameworks.system.text.RegularExpressions import semmle.code.csharp.security.xml.InsecureXML diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll index e2ef4797dfe..7c84561cf44 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XPathInjection.qll @@ -5,7 +5,7 @@ import csharp module XPathInjection { - import semmle.code.csharp.dataflow.flowsources.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote import semmle.code.csharp.frameworks.system.xml.XPath import semmle.code.csharp.frameworks.system.Xml import semmle.code.csharp.security.Sanitizers diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll index 513b0b89f00..635c59363f5 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/XSS.qll @@ -6,17 +6,14 @@ import csharp module XSS { - import semmle.code.csharp.dataflow.flowsources.Remote - import semmle.code.csharp.frameworks.microsoft.AspNetCore + import semmle.code.asp.AspNet import semmle.code.csharp.frameworks.system.Net import semmle.code.csharp.frameworks.system.Web - import semmle.code.csharp.frameworks.system.web.Mvc - import semmle.code.csharp.frameworks.system.web.WebPages import semmle.code.csharp.frameworks.system.web.UI - import semmle.code.csharp.frameworks.system.web.ui.WebControls - import semmle.code.csharp.frameworks.system.windows.Forms import semmle.code.csharp.security.Sanitizers - import semmle.code.asp.AspNet + import semmle.code.csharp.security.dataflow.flowsinks.Html + import semmle.code.csharp.security.dataflow.flowsinks.Remote + import semmle.code.csharp.security.dataflow.flowsources.Remote /** * Holds if there is tainted flow from `source` to `sink` that may lead to a @@ -112,8 +109,11 @@ module XSS { /** * A data flow sink for cross-site scripting (XSS) vulnerabilities. + * + * Any XSS sink is also a remote flow sink, so this class contributes + * to the abstract class `RemoteFlowSink`. */ - abstract class Sink extends DataFlow::ExprNode { + abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { string explanation() { none() } } @@ -166,78 +166,21 @@ module XSS { UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr } } - /** A sink where the value of the expression may be rendered as HTML. */ - abstract class HtmlSink extends DataFlow::Node { } + private class HtmlSinkSink extends Sink { + HtmlSinkSink() { this instanceof HtmlSink } - /** - * An expression that is used as an argument to an XSS sink method on - * `HttpResponse`. - */ - private class HttpResponseSink extends Sink, HtmlSink { - HttpResponseSink() { - exists(Method m, SystemWebHttpResponseClass responseClass | - m = responseClass.getAWriteMethod() or - m = responseClass.getAWriteFileMethod() or - m = responseClass.getATransmitFileMethod() or - m = responseClass.getABinaryWriteMethod() - | - // Calls to these methods, or overrides of them - this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() - ) - } - } - - /** - * An expression that is used as an argument to an XSS sink method on - * `HtmlTextWriter`. - */ - private class HtmlTextWriterSink extends Sink, HtmlSink { - HtmlTextWriterSink() { - exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos | - paramPos = 0 and - ( - m = writeClass.getAWriteMethod() or - m = writeClass.getAWriteLineMethod() or - m = writeClass.getAWriteLineNoTabsMethod() or - m = writeClass.getAWriteBeginTagMethod() or - m = writeClass.getAWriteAttributeMethod() - ) - or - // The second parameter to the `WriteAttribute` method is the attribute value, which we - // should only consider as tainted if the call does not ask for the attribute value to be - // encoded using the final parameter. - m = writeClass.getAWriteAttributeMethod() and - paramPos = 1 and - not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true - | - c = m.getACall() and - this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos)) - ) - } - } - - /** - * An expression that is used as an argument to an XSS sink method on - * `AttributeCollection`. - */ - private class AttributeCollectionSink extends Sink, HtmlSink { - AttributeCollectionSink() { - exists(SystemWebUIAttributeCollectionClass ac, Parameter p | - p = ac.getAddMethod().getParameter(1) or - p = ac.getItemProperty().getSetter().getParameter(0) - | - this.getExpr() = p.getAnAssignedArgument() - ) - } - } - - /** - * An expression that is used as the second argument `HtmlElement.SetAttribute`. - */ - private class SetAttributeSink extends Sink, HtmlSink { - SetAttributeSink() { - this.getExpr() = - any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1) + override string explanation() { + this instanceof WebPageWriteLiteralSink and + result = "System.Web.WebPages.WebPage.WriteLiteral() method" + or + this instanceof WebPageWriteLiteralToSink and + result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" + or + this instanceof MicrosoftAspNetCoreMvcHtmlHelperRawSink and + result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method" + or + this instanceof MicrosoftAspNetRazorPageWriteLiteralSink and + result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method" } } @@ -285,31 +228,6 @@ module XSS { } } - /** - * An expression that is used as an argument to an XSS sink setter, on - * a class within the `System.Web.UI` namespace. - */ - private class SystemWebSetterHtmlSink extends Sink, HtmlSink { - SystemWebSetterHtmlSink() { - exists(Property p, string name, ValueOrRefType declaringType | - declaringType = p.getDeclaringType() and - any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and - this.getExpr() = p.getSetter().getParameter(0).getAnAssignedArgument() and - p.hasName(name) - | - name = "Caption" and - (declaringType.hasName("Calendar") or declaringType.hasName("Table")) - or - name = "InnerHtml" - ) - or - exists(SystemWebUIWebControlsLabelClass c | - // Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded - this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument() - ) - } - } - /** * An expression that is used as an argument to an XSS sink setter, on * a class within the `System.Web.UI` namespace. @@ -345,16 +263,6 @@ module XSS { } } - /** - * An expression that is used as an argument to `HtmlHelper.Raw`, typically in - * a `.cshtml` file. - */ - private class SystemWebMvcHtmlHelperRawSink extends Sink, HtmlSink { - SystemWebMvcHtmlHelperRawSink() { - this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() - } - } - /** * Gets a member which is accessed by the given `AspInlineCode`. * The code body must consist only of an access to the member, possibly with qualified @@ -493,31 +401,6 @@ module XSS { } } - /** An expression that is returned from a `ToHtmlString` method. */ - private class ToHtmlString extends Sink, HtmlSink { - ToHtmlString() { - exists(Method toHtmlString | - toHtmlString = - any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and - toHtmlString.canReturn(this.getExpr()) - ) - } - } - - /** - * An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`. - */ - private class HtmlString extends Sink, HtmlSink { - HtmlString() { - exists(Class c | - c = any(SystemWebMvcMvcHtmlString m) or - c = any(SystemWebHtmlString m) - | - this.getExpr() = c.getAConstructor().getACall().getAnArgument() - ) - } - } - /** * An expression passed as the `content` argument to the constructor of `StringContent`. */ @@ -529,75 +412,6 @@ module XSS { ).getArgumentForName("content") } } - - /** - * An expression that is used as an argument to `Page.WriteLiteral`, typically in - * a `.cshtml` file. - */ - class WebPageWriteLiteralSink extends Sink, HtmlSink { - WebPageWriteLiteralSink() { - this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() - } - - override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteral() method" } - } - - /** - * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in - * a `.cshtml` file. - */ - class WebPageWriteLiteralToSink extends Sink, HtmlSink { - WebPageWriteLiteralToSink() { - this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() - } - - override string explanation() { result = "System.Web.WebPages.WebPage.WriteLiteralTo() method" } - } - - abstract class AspNetCoreSink extends Sink, HtmlSink { } - - /** - * An expression that is used as an argument to `HtmlHelper.Raw`, typically in - * a `.cshtml` file. - */ - class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreSink { - MicrosoftAspNetCoreMvcHtmlHelperRawSink() { - this.getExpr() = - any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() - } - - override string explanation() { - result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method" - } - } - - /** - * An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in - * a `.cshtml` file. - */ - class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreSink { - MicrosoftAspNetRazorPageWriteLiteralSink() { - this.getExpr() = - any(MicrosoftAspNetCoreMvcRazorPageBase h) - .getWriteLiteralMethod() - .getACall() - .getAnArgument() - } - - override string explanation() { - result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method" - } - } - - /** `HtmlString` that may be rendered as is need to have sanitized value. */ - class MicrosoftAspNetHtmlStringSink extends AspNetCoreSink { - MicrosoftAspNetHtmlStringSink() { - exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | - c.getTarget() = s.getAConstructor() and - this.asExpr() = c.getAnArgument() - ) - } - } } private Type getMemberType(Member m) { diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll similarity index 88% rename from csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll index b86fa4822ae..c45bd9e8b39 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/Email.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Email.qll @@ -1,11 +1,13 @@ /** Provides data flow sinks for sending email. */ import csharp +private import Remote private import semmle.code.csharp.frameworks.system.net.Mail +/** Provides sinks for emails. */ module Email { /** A data flow sink for sending email. */ - abstract class Sink extends DataFlow::ExprNode { } + abstract class Sink extends DataFlow::ExprNode, RemoteFlowSink { } /** A data flow sink for sending email via `System.Net.Mail.MailMessage`. */ class MailMessageSink extends Sink { diff --git a/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll similarity index 95% rename from csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll index 6cd1a5cb269..25a50f3733c 100644 --- a/csharp/ql/src/semmle/code/csharp/security/sinks/ExternalLocationSink.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/ExternalLocationSink.qll @@ -3,6 +3,7 @@ */ import csharp +private import Remote private import semmle.code.csharp.commons.Loggers private import semmle.code.csharp.frameworks.system.Web @@ -45,7 +46,7 @@ class TraceMessageSink extends ExternalLocationSink { /** * An expression set as a value on a cookie instance. */ -class CookieStorageSink extends ExternalLocationSink { +class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink { CookieStorageSink() { exists(Expr e | e = this.getExpr() | e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value") diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll new file mode 100644 index 00000000000..2363e24ffeb --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Html.qll @@ -0,0 +1,208 @@ +/** + * Provides classes representing HTML data flow sinks. + */ + +import csharp +private import Remote +private import semmle.code.csharp.frameworks.microsoft.AspNetCore +private import semmle.code.csharp.frameworks.system.Net +private import semmle.code.csharp.frameworks.system.Web +private import semmle.code.csharp.frameworks.system.web.Mvc +private import semmle.code.csharp.frameworks.system.web.WebPages +private import semmle.code.csharp.frameworks.system.web.UI +private import semmle.code.csharp.frameworks.system.web.ui.WebControls +private import semmle.code.csharp.frameworks.system.windows.Forms +private import semmle.code.csharp.security.dataflow.flowsources.Remote +private import semmle.code.asp.AspNet + +/** + * A sink where the value of the expression may be rendered as HTML, + * without implicit HTML encoding. + */ +abstract class HtmlSink extends DataFlow::ExprNode, RemoteFlowSink { } + +/** + * An expression that is used as an argument to an HTML sink method on + * `HttpResponse`. + */ +class HttpResponseSink extends HtmlSink { + HttpResponseSink() { + exists(Method m, SystemWebHttpResponseClass responseClass | + m = responseClass.getAWriteMethod() or + m = responseClass.getAWriteFileMethod() or + m = responseClass.getATransmitFileMethod() or + m = responseClass.getABinaryWriteMethod() + | + // Calls to these methods, or overrides of them + this.getExpr() = m.getAnOverrider*().getParameter(0).getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as an argument to an HTML sink method on + * `HtmlTextWriter`. + */ +class HtmlTextWriterSink extends HtmlSink { + HtmlTextWriterSink() { + exists(SystemWebUIHtmlTextWriterClass writeClass, Method m, Call c, int paramPos | + paramPos = 0 and + ( + m = writeClass.getAWriteMethod() or + m = writeClass.getAWriteLineMethod() or + m = writeClass.getAWriteLineNoTabsMethod() or + m = writeClass.getAWriteBeginTagMethod() or + m = writeClass.getAWriteAttributeMethod() + ) + or + // The second parameter to the `WriteAttribute` method is the attribute value, which we + // should only consider as tainted if the call does not ask for the attribute value to be + // encoded using the final parameter. + m = writeClass.getAWriteAttributeMethod() and + paramPos = 1 and + not c.getArgumentForParameter(m.getParameter(2)).(BoolLiteral).getBoolValue() = true + | + c = m.getACall() and + this.getExpr() = c.getArgumentForParameter(m.getParameter(paramPos)) + ) + } +} + +/** + * An expression that is used as an argument to an HTML sink method on + * `AttributeCollection`. + */ +class AttributeCollectionSink extends HtmlSink { + AttributeCollectionSink() { + exists(SystemWebUIAttributeCollectionClass ac, Parameter p | + p = ac.getAddMethod().getParameter(1) or + p = ac.getItemProperty().getSetter().getParameter(0) + | + this.getExpr() = p.getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as the second argument `HtmlElement.SetAttribute`. + */ +class SetAttributeSink extends HtmlSink { + SetAttributeSink() { + this.getExpr() = + any(SystemWindowsFormsHtmlElement c).getSetAttributeMethod().getACall().getArgument(1) + } +} + +/** + * An expression that is used as an argument to an HTML sink setter, on + * a class within the `System.Web.UI` namespace. + */ +class SystemWebSetterHtmlSink extends HtmlSink { + SystemWebSetterHtmlSink() { + exists(Property p, string name, ValueOrRefType declaringType | + declaringType = p.getDeclaringType() and + any(SystemWebUINamespace n).getAChildNamespace*() = declaringType.getNamespace() and + this.getExpr() = p.getAnAssignedValue() and + p.hasName(name) + | + name = "Caption" and + (declaringType.hasName("Calendar") or declaringType.hasName("Table")) + or + name = "InnerHtml" + ) + or + exists(SystemWebUIWebControlsLabelClass c | + // Unlike `Text` properties of other web controls, `Label.Text` is not automatically HTML encoded + this.getExpr() = c.getTextProperty().getSetter().getParameter(0).getAnAssignedArgument() + ) + } +} + +/** + * An expression that is used as an argument to `HtmlHelper.Raw`, typically in + * a `.cshtml` file. + */ +class SystemWebMvcHtmlHelperRawSink extends HtmlSink { + SystemWebMvcHtmlHelperRawSink() { + this.getExpr() = any(SystemWebMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + } +} + +/** An expression that is returned from a `ToHtmlString` method. */ +class ToHtmlString extends HtmlSink { + ToHtmlString() { + exists(Method toHtmlString | + toHtmlString = any(SystemWebIHtmlString i).getToHtmlStringMethod().getAnUltimateImplementor() and + toHtmlString.canReturn(this.getExpr()) + ) + } +} + +/** + * An expression passed to the constructor of an `HtmlString` or a `MvcHtmlString`. + */ +class HtmlString extends HtmlSink { + HtmlString() { + exists(Class c | + c = any(SystemWebMvcMvcHtmlString m) or + c = any(SystemWebHtmlString m) + | + this.getExpr() = c.getAConstructor().getACall().getAnArgument() + ) + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteral`, typically in + * a `.cshtml` file. + */ +class WebPageWriteLiteralSink extends HtmlSink { + WebPageWriteLiteralSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralMethod().getACall().getAnArgument() + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteralTo`, typically in + * a `.cshtml` file. + */ +class WebPageWriteLiteralToSink extends HtmlSink { + WebPageWriteLiteralToSink() { + this.getExpr() = any(WebPageClass h).getWriteLiteralToMethod().getACall().getAnArgument() + } +} + +/** An ASP.NET Core HTML sink. */ +abstract class AspNetCoreHtmlSink extends HtmlSink { } + +/** + * An expression that is used as an argument to `HtmlHelper.Raw`, typically in + * a `.cshtml` file. + */ +class MicrosoftAspNetCoreMvcHtmlHelperRawSink extends AspNetCoreHtmlSink { + MicrosoftAspNetCoreMvcHtmlHelperRawSink() { + this.getExpr() = + any(MicrosoftAspNetCoreMvcHtmlHelperClass h).getRawMethod().getACall().getAnArgument() + } +} + +/** + * An expression that is used as an argument to `Page.WriteLiteral` in ASP.NET 6.0 razor page, typically in + * a `.cshtml` file. + */ +class MicrosoftAspNetRazorPageWriteLiteralSink extends AspNetCoreHtmlSink { + MicrosoftAspNetRazorPageWriteLiteralSink() { + this.getExpr() = + any(MicrosoftAspNetCoreMvcRazorPageBase h).getWriteLiteralMethod().getACall().getAnArgument() + } +} + +/** `HtmlString` that may be rendered as is need to have sanitized value. */ +class MicrosoftAspNetHtmlStringSink extends AspNetCoreHtmlSink { + MicrosoftAspNetHtmlStringSink() { + exists(ObjectCreation c, MicrosoftAspNetCoreHttpHtmlString s | + c.getTarget() = s.getAConstructor() and + this.asExpr() = c.getAnArgument() + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll new file mode 100644 index 00000000000..10885d52a16 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsinks/Remote.qll @@ -0,0 +1,31 @@ +/** + * Provides classes representing data flow sinks for remote user output. + */ + +import csharp +private import Email::Email +private import ExternalLocationSink +private import Html +private import semmle.code.csharp.security.dataflow.XSS +private import semmle.code.csharp.frameworks.system.web.UI + +/** A data flow sink of remote user output. */ +abstract class RemoteFlowSink extends DataFlow::Node { } + +/** + * A value written to the `[Inner]Text` property of an object defined in the + * `System.Web.UI` namespace. + */ +class SystemWebUIText extends RemoteFlowSink { + SystemWebUIText() { + exists(Property p, string name | + p.getDeclaringType().getNamespace().getParentNamespace*() instanceof SystemWebUINamespace and + this.asExpr() = p.getAnAssignedValue() and + p.hasName(name) + | + name = "Text" + or + name = "InnerText" + ) + } +} diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Local.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Local.qll similarity index 100% rename from csharp/ql/src/semmle/code/csharp/dataflow/flowsources/Local.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Local.qll diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll new file mode 100644 index 00000000000..f8240583108 --- /dev/null +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -0,0 +1,218 @@ +/** + * Provides classes representing data flow sources for remote user input. + */ + +import csharp +private import semmle.code.csharp.frameworks.system.Net +private import semmle.code.csharp.frameworks.system.Web +private import semmle.code.csharp.frameworks.system.web.Http +private import semmle.code.csharp.frameworks.system.web.Mvc +private import semmle.code.csharp.frameworks.system.web.Services +private import semmle.code.csharp.frameworks.system.web.ui.WebControls +private import semmle.code.csharp.frameworks.WCF +private import semmle.code.csharp.frameworks.microsoft.Owin +private import semmle.code.csharp.frameworks.microsoft.AspNetCore + +/** A data flow source of remote user input. */ +abstract class RemoteFlowSource extends DataFlow::Node { + /** Gets a string that describes the type of this remote flow source. */ + abstract string getSourceType(); +} + +/** A data flow source of remote user input (ASP.NET). */ +abstract class AspNetRemoteFlowSource extends RemoteFlowSource { } + +/** A member containing an ASP.NET query string. */ +class AspNetQueryStringMember extends Member { + AspNetQueryStringMember() { + exists(RefType t | + t instanceof SystemWebHttpRequestClass or + t instanceof SystemNetHttpListenerRequestClass or + t instanceof SystemWebHttpRequestBaseClass + | + this = t.getProperty(getHttpRequestFlowPropertyNames()) or + this.(Field).getType() = t or + this.(Property).getType() = t or + this.(Callable).getReturnType() = t + ) + } +} + +/** + * Gets the names of the properties in `HttpRequest` classes that should propagate taint out of the + * request. + */ +private string getHttpRequestFlowPropertyNames() { + result = "QueryString" or + result = "Headers" or + result = "RawUrl" or + result = "Url" or + result = "Cookies" or + result = "Form" or + result = "Params" or + result = "Path" or + result = "PathInfo" +} + +/** A data flow source of remote user input (ASP.NET query string). */ +class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { + AspNetQueryStringRemoteFlowSource() { + exists(RefType t | + t instanceof SystemWebHttpRequestClass or + t instanceof SystemNetHttpListenerRequestClass or + t instanceof SystemWebHttpRequestBaseClass + | + // A request object can be indexed, so taint the object as well + this.getExpr().getType() = t + ) + or + this.getExpr() = any(AspNetQueryStringMember m).getAnAccess() + } + + override string getSourceType() { result = "ASP.NET query string" } +} + +/** A data flow source of remote user input (ASP.NET unvalidated request data). */ +class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, + DataFlow::ExprNode { + AspNetUnvalidatedQueryStringRemoteFlowSource() { + this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or + this.getExpr() = + any(SystemWebUnvalidatedRequestValuesBase c).getAProperty().getGetter().getACall() + } + + override string getSourceType() { result = "ASP.NET unvalidated request data" } +} + +/** A data flow source of remote user input (ASP.NET user input). */ +class AspNetUserInputRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow::ExprNode { + AspNetUserInputRemoteFlowSource() { getType() instanceof SystemWebUIWebControlsTextBoxClass } + + override string getSourceType() { result = "ASP.NET user input" } +} + +/** A data flow source of remote user input (WCF based web service). */ +class WcfRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { + WcfRemoteFlowSource() { exists(OperationMethod om | om.getAParameter() = this.getParameter()) } + + override string getSourceType() { result = "web service input" } +} + +/** A data flow source of remote user input (ASP.NET web service). */ +class AspNetServiceRemoteFlowSource extends RemoteFlowSource, DataFlow::ParameterNode { + AspNetServiceRemoteFlowSource() { + exists(Method m | + m.getAParameter() = this.getParameter() and + m.getAnAttribute().getType() instanceof SystemWebServicesWebMethodAttributeClass + ) + } + + override string getSourceType() { result = "ASP.NET web service input" } +} + +/** A data flow source of remote user input (ASP.NET request message). */ +class SystemNetHttpRequestMessageRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + SystemNetHttpRequestMessageRemoteFlowSource() { + getType() instanceof SystemWebHttpRequestMessageClass + } + + override string getSourceType() { result = "ASP.NET request message" } +} + +/** + * A data flow source of remote user input (Microsoft Owin, a query, request, + * or path string). + */ +class MicrosoftOwinStringFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + MicrosoftOwinStringFlowSource() { + this.getExpr() = any(MicrosoftOwinString owinString).getValueProperty().getGetter().getACall() + } + + override string getSourceType() { result = "Microsoft Owin request or query string" } +} + +/** A data flow source of remote user input (`Microsoft Owin IOwinRequest`). */ +class MicrosoftOwinRequestRemoteFlowSource extends RemoteFlowSource, DataFlow::ExprNode { + MicrosoftOwinRequestRemoteFlowSource() { + exists(Property p, MicrosoftOwinIOwinRequestClass owinRequest | + this.getExpr() = p.getGetter().getACall() + | + p = owinRequest.getAcceptProperty() or + p = owinRequest.getBodyProperty() or + p = owinRequest.getCacheControlProperty() or + p = owinRequest.getContentTypeProperty() or + p = owinRequest.getContextProperty() or + p = owinRequest.getCookiesProperty() or + p = owinRequest.getHeadersProperty() or + p = owinRequest.getHostProperty() or + p = owinRequest.getMediaTypeProperty() or + p = owinRequest.getMethodProperty() or + p = owinRequest.getPathProperty() or + p = owinRequest.getPathBaseProperty() or + p = owinRequest.getQueryProperty() or + p = owinRequest.getQueryStringProperty() or + p = owinRequest.getRemoteIpAddressProperty() or + p = owinRequest.getSchemeProperty() or + p = owinRequest.getURIProperty() + ) + } + + override string getSourceType() { result = "Microsoft Owin request" } +} + +/** A parameter to an Mvc controller action method, viewed as a source of remote user input. */ +class ActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { + ActionMethodParameter() { + exists(Parameter p | + p = this.getParameter() and + p.fromSource() + | + p = any(Controller c).getAnActionMethod().getAParameter() or + p = any(ApiController c).getAnActionMethod().getAParameter() + ) + } + + override string getSourceType() { result = "ASP.NET MVC action method parameter" } +} + +/** A data flow source of remote user input (ASP.NET Core). */ +abstract class AspNetCoreRemoteFlowSource extends RemoteFlowSource { } + +/** A data flow source of remote user input (ASP.NET query collection). */ +class AspNetCoreQueryRemoteFlowSource extends AspNetCoreRemoteFlowSource, DataFlow::ExprNode { + AspNetCoreQueryRemoteFlowSource() { + exists(ValueOrRefType t | + t instanceof MicrosoftAspNetCoreHttpHttpRequest or + t instanceof MicrosoftAspNetCoreHttpQueryCollection or + t instanceof MicrosoftAspNetCoreHttpQueryString + | + this.getExpr().(Call).getTarget().getDeclaringType() = t or + this.asExpr().(Access).getTarget().getDeclaringType() = t + ) + or + exists(Call c | + c + .getTarget() + .getDeclaringType() + .hasQualifiedName("Microsoft.AspNetCore.Http", "IQueryCollection") and + c.getTarget().getName() = "TryGetValue" and + this.asExpr() = c.getArgumentForName("value") + ) + } + + override string getSourceType() { result = "ASP.NET Core query string" } +} + +/** A parameter to a `Mvc` controller action method, viewed as a source of remote user input. */ +class AspNetCoreActionMethodParameter extends RemoteFlowSource, DataFlow::ParameterNode { + AspNetCoreActionMethodParameter() { + exists(Parameter p | + p = this.getParameter() and + p.fromSource() + | + p = any(MicrosoftAspNetCoreMvcController c).getAnActionMethod().getAParameter() + ) + } + + override string getSourceType() { result = "ASP.NET Core MVC action method parameter" } +} diff --git a/csharp/ql/test/library-tests/aliases/aliases2.expected b/csharp/ql/test/library-tests/aliases/aliases2.expected index 45870c5dda2..05fad62d6a8 100644 --- a/csharp/ql/test/library-tests/aliases/aliases2.expected +++ b/csharp/ql/test/library-tests/aliases/aliases2.expected @@ -1,3 +1,9 @@ | Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class | +| Program.cs:18:21:18:22 | c1 | Assembly2.dll:0:0:0:0 | Class | +| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class | +| Program.cs:19:21:19:22 | c2 | Assembly1.dll:0:0:0:0 | Class | | Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class | +| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class | +| Program.cs:20:15:20:16 | c3 | Assembly1.dll:0:0:0:0 | Class | +| Program.cs:20:15:20:16 | c3 | Assembly2.dll:0:0:0:0 | Class | | Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class | diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected index db4f3c6fb5d..891ba1602cb 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected @@ -243,7 +243,7 @@ expressionTypes | NullableRefTypes.cs:19:33:19:36 | this access | MyClass! | | NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass![]! | | NullableRefTypes.cs:26:50:26:53 | null | null | -| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass![]! | +| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass?[]! | | NullableRefTypes.cs:27:50:27:53 | null | null | | NullableRefTypes.cs:30:21:30:24 | null | null | | NullableRefTypes.cs:31:20:31:23 | this access | MyClass! | diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs new file mode 100644 index 00000000000..3565ba0b6ea --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.cs @@ -0,0 +1,231 @@ +// semmle-extractor-options: /r:System.Linq.dll +using System; +using System.Collections.Generic; +using System.Linq; + +public class CollectionFlow +{ + public class A { } + + public void ArrayInitializerFlow() + { + var a = new A(); + var @as = new[] { a }; + Sink(@as[0]); // flow + SinkElem(@as); // flow + Sink(First(@as)); // flow + } + + public void ArrayInitializerNoFlow(A other) + { + var a = new A(); + var @as = new[] { other }; + Sink(@as[0]); // no flow + SinkElem(@as); // no flow + Sink(First(@as)); // no flow + } + + public void ArrayAssignmentFlow() + { + var a = new A(); + var @as = new A[1]; + @as[0] = a; + Sink(@as[0]); // flow + SinkElem(@as); // flow + Sink(First(@as)); // flow + } + + public void ArrayAssignmentNoFlow(A other) + { + var a = new A(); + var @as = new A[1]; + @as[0] = other; + Sink(@as[0]); // no flow + SinkElem(@as); // no flow + Sink(First(@as)); // no flow + } + + public void ListAssignmentFlow() + { + var a = new A(); + var list = new List(); + list[0] = a; + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void ListAssignmentNoFlow(A other) + { + var list = new List(); + list[0] = other; + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void ListInitializerFlow() + { + var a = new A(); + var list = new List() { a }; + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void ListInitializerNoFlow(A other) + { + var list = new List() { other }; + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void ListAddFlow() + { + var a = new A(); + var list = new List(); + list.Add(a); + Sink(list[0]); // flow + SinkListElem(list); // flow + Sink(ListFirst(list)); // flow + } + + public void ListAddNoFlow(A other) + { + var list = new List(); + list.Add(other); + Sink(list[0]); // no flow + SinkListElem(list); // no flow + Sink(ListFirst(list)); // no flow + } + + public void DictionaryAssignmentFlow() + { + var a = new A(); + var dict = new Dictionary(); + dict[0] = a; + Sink(dict[0]); // flow + SinkDictValue(dict); // flow + Sink(DictIndexZero(dict)); // flow + Sink(DictFirstValue(dict)); // flow [MISSING] + Sink(DictValuesFirst(dict)); // flow + } + + public void DictionaryAssignmentNoFlow(A other) + { + var dict = new Dictionary(); + dict[0] = other; + Sink(dict[0]); // no flow + SinkDictValue(dict); // no flow + Sink(DictIndexZero(dict)); // no flow + Sink(DictFirstValue(dict)); // no flow + Sink(DictValuesFirst(dict)); // no flow + } + + public void DictionaryValueInitializerFlow() + { + var a = new A(); + var dict = new Dictionary() { { 0, a } }; + Sink(dict[0]); // flow + SinkDictValue(dict); // flow + Sink(DictIndexZero(dict)); // flow + Sink(DictFirstValue(dict)); // flow [MISSING] + Sink(DictValuesFirst(dict)); // flow + } + + public void DictionaryValueInitializerNoFlow(A other) + { + var dict = new Dictionary() { { 0, other } }; + Sink(dict[0]); // no flow + SinkDictValue(dict); // no flow + Sink(DictIndexZero(dict)); // no flow + Sink(DictFirstValue(dict)); // no flow + Sink(DictValuesFirst(dict)); // no flow + } + + public void DictionaryKeyInitializerFlow() + { + var a = new A(); + var dict = new Dictionary() { { a, 0 } }; + Sink(dict.Keys.First()); // flow [MISSING] + SinkDictKey(dict); // flow [MISSING] + Sink(DictKeysFirst(dict)); // flow [MISSING] + Sink(DictFirstKey(dict)); // flow [MISSING] + } + + public void DictionaryKeyInitializerNoFlow(A other) + { + var dict = new Dictionary() { { other, 0 } }; + Sink(dict.Keys.First()); // no flow + SinkDictKey(dict); // no flow + Sink(DictKeysFirst(dict)); // no flow + Sink(DictFirstKey(dict)); // no flow + } + + public void ForeachFlow() + { + var a = new A(); + var @as = new[] { a }; + foreach (var x in @as) + Sink(x); // flow + } + + public void ForeachNoFlow(A other) + { + var @as = new[] { other }; + foreach (var x in @as) + Sink(x); // no flow + } + + public void ArrayGetEnumeratorFlow() + { + var a = new A(); + var @as = new[] { a }; + var enumerator = @as.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // flow + } + + public void ArrayGetEnumeratorNoFlow(A other) + { + var @as = new[] { other }; + var enumerator = @as.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // no flow + } + + public void ListGetEnumeratorFlow() + { + var a = new A(); + var list = new List(); + list.Add(a); + var enumerator = list.GetEnumerator(); + while (enumerator.MoveNext()) + Sink(enumerator.Current); // flow [MISSING] + } + + public static void Sink(T t) { } + + public static void SinkElem(T[] ts) => Sink(ts[0]); + + public static void SinkListElem(IList list) => Sink(list[0]); + + public static void SinkDictValue(IDictionary dict) => Sink(dict[0]); + + public static void SinkDictKey(IDictionary dict) => Sink(dict.Keys.First()); + + public static T First(T[] ts) => ts[0]; + + public static T ListFirst(IList list) => list[0]; + + public static T DictIndexZero(IDictionary dict) => dict[0]; + + public static T DictFirstValue(IDictionary dict) => dict.First().Value; + + public static T DictValuesFirst(IDictionary dict) => dict.Values.First(); + + public static T DictKeysFirst(IDictionary dict) => dict.Keys.First(); + + public static T DictFirstKey(IDictionary dict) => dict.First().Key; +} diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected new file mode 100644 index 00000000000..c6cc298ea94 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.expected @@ -0,0 +1,235 @@ +edges +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:19 | access to array element | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | +| CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | CollectionFlow.cs:210:40:210:41 | ts : A[] | +| CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | CollectionFlow.cs:16:14:16:23 | call to method First | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:19 | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | +| CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | CollectionFlow.cs:210:40:210:41 | ts : A[] | +| CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | CollectionFlow.cs:35:14:35:23 | call to method First | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:20 | access to indexer | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:54:22:54:25 | access to local variable list : List | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:55:24:55:27 | access to local variable list : List | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:20 | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:54:22:54:25 | access to local variable list : List | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:55:24:55:27 | access to local variable list : List | +| CollectionFlow.cs:54:22:54:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:55:24:55:27 | access to local variable list : List | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:20 | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:63:22:63:25 | access to local variable list : List | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:64:24:64:27 | access to local variable list : List | +| CollectionFlow.cs:63:22:63:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:64:24:64:27 | access to local variable list : List | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:20 | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:72:22:72:25 | access to local variable list : List | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:73:24:73:27 | access to local variable list : List | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:20 | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:72:22:72:25 | access to local variable list : List | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:73:24:73:27 | access to local variable list : List | +| CollectionFlow.cs:72:22:72:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:73:24:73:27 | access to local variable list : List | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:20 | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:80:22:80:25 | access to local variable list : List | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:81:24:81:27 | access to local variable list : List | +| CollectionFlow.cs:80:22:80:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:81:24:81:27 | access to local variable list : List | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:20 | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:90:22:90:25 | access to local variable list : List | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:91:24:91:27 | access to local variable list : List | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:20 | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:90:22:90:25 | access to local variable list : List | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:91:24:91:27 | access to local variable list : List | +| CollectionFlow.cs:90:22:90:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:91:24:91:27 | access to local variable list : List | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:20 | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:99:22:99:25 | access to local variable list : List | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:100:24:100:27 | access to local variable list : List | +| CollectionFlow.cs:99:22:99:25 | access to local variable list : List | CollectionFlow.cs:212:49:212:52 | list : List | +| CollectionFlow.cs:100:24:100:27 | access to local variable list : List | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:20 | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:20 | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | +| CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:20 | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | +| CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:20 | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:20 | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | +| CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:20 | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | +| CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | CollectionFlow.cs:214:61:214:64 | dict : Dictionary | +| CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | +| CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:171:18:171:18 | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:187:18:187:35 | access to property Current | +| CollectionFlow.cs:210:40:210:41 | ts : A[] | CollectionFlow.cs:210:52:210:56 | access to array element | +| CollectionFlow.cs:212:49:212:52 | list : List | CollectionFlow.cs:212:63:212:69 | access to indexer | +| CollectionFlow.cs:214:61:214:64 | dict : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | +nodes +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:14:14:14:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:15:18:15:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:16:14:16:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:16:20:16:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:33:14:33:19 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:34:18:34:20 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:35:14:35:23 | call to method First | semmle.label | call to method First | +| CollectionFlow.cs:35:20:35:22 | access to local variable as : A[] | semmle.label | access to local variable as : A[] | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:53:14:53:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:54:22:54:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:55:14:55:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:55:24:55:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:62:14:62:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:63:22:63:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:64:14:64:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:64:24:64:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:71:14:71:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:72:22:72:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:73:14:73:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:73:24:73:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:79:14:79:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:80:22:80:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:81:14:81:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:81:24:81:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:89:14:89:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:90:22:90:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:91:14:91:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:91:24:91:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | semmle.label | object creation of type List : List | +| CollectionFlow.cs:98:14:98:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:99:22:99:25 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:100:14:100:28 | call to method ListFirst | semmle.label | call to method ListFirst | +| CollectionFlow.cs:100:24:100:27 | access to local variable list : List | semmle.label | access to local variable list : List | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:108:14:108:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:109:23:109:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:110:28:110:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:112:30:112:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:119:14:119:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:120:23:120:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:121:28:121:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:123:30:123:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:130:14:130:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:131:23:131:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:132:28:132:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:134:30:134:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | semmle.label | object creation of type Dictionary : Dictionary | +| CollectionFlow.cs:140:14:140:20 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:141:23:141:26 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | semmle.label | call to method DictIndexZero | +| CollectionFlow.cs:142:28:142:31 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | semmle.label | call to method DictValuesFirst | +| CollectionFlow.cs:144:30:144:33 | access to local variable dict : Dictionary | semmle.label | access to local variable dict : Dictionary | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:171:18:171:18 | access to local variable x | semmle.label | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | semmle.label | object creation of type A : A | +| CollectionFlow.cs:187:18:187:35 | access to property Current | semmle.label | access to property Current | +| CollectionFlow.cs:210:40:210:41 | ts : A[] | semmle.label | ts : A[] | +| CollectionFlow.cs:210:52:210:56 | access to array element | semmle.label | access to array element | +| CollectionFlow.cs:212:49:212:52 | list : List | semmle.label | list : List | +| CollectionFlow.cs:212:63:212:69 | access to indexer | semmle.label | access to indexer | +| CollectionFlow.cs:214:61:214:64 | dict : Dictionary | semmle.label | dict : Dictionary | +| CollectionFlow.cs:214:75:214:81 | access to indexer | semmle.label | access to indexer | +#select +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:14:14:14:19 | access to array element | $@ | CollectionFlow.cs:14:14:14:19 | access to array element | access to array element | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:16:14:16:23 | call to method First | $@ | CollectionFlow.cs:16:14:16:23 | call to method First | call to method First | +| CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:12:17:12:23 | object creation of type A : A | CollectionFlow.cs:210:52:210:56 | access to array element | $@ | CollectionFlow.cs:210:52:210:56 | access to array element | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:33:14:33:19 | access to array element | $@ | CollectionFlow.cs:33:14:33:19 | access to array element | access to array element | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:35:14:35:23 | call to method First | $@ | CollectionFlow.cs:35:14:35:23 | call to method First | call to method First | +| CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:30:17:30:23 | object creation of type A : A | CollectionFlow.cs:210:52:210:56 | access to array element | $@ | CollectionFlow.cs:210:52:210:56 | access to array element | access to array element | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:53:14:53:20 | access to indexer | $@ | CollectionFlow.cs:53:14:53:20 | access to indexer | access to indexer | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | $@ | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:50:17:50:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:53:14:53:20 | access to indexer | $@ | CollectionFlow.cs:53:14:53:20 | access to indexer | access to indexer | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | $@ | CollectionFlow.cs:55:14:55:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:51:20:51:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:62:14:62:20 | access to indexer | $@ | CollectionFlow.cs:62:14:62:20 | access to indexer | access to indexer | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | $@ | CollectionFlow.cs:64:14:64:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:60:20:60:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:71:14:71:20 | access to indexer | $@ | CollectionFlow.cs:71:14:71:20 | access to indexer | access to indexer | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | $@ | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:69:17:69:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:71:14:71:20 | access to indexer | $@ | CollectionFlow.cs:71:14:71:20 | access to indexer | access to indexer | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | $@ | CollectionFlow.cs:73:14:73:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:70:20:70:38 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:79:14:79:20 | access to indexer | $@ | CollectionFlow.cs:79:14:79:20 | access to indexer | access to indexer | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | $@ | CollectionFlow.cs:81:14:81:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:78:20:78:42 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:89:14:89:20 | access to indexer | $@ | CollectionFlow.cs:89:14:89:20 | access to indexer | access to indexer | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | $@ | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:86:17:86:23 | object creation of type A : A | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:89:14:89:20 | access to indexer | $@ | CollectionFlow.cs:89:14:89:20 | access to indexer | access to indexer | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | $@ | CollectionFlow.cs:91:14:91:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:87:20:87:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:98:14:98:20 | access to indexer | $@ | CollectionFlow.cs:98:14:98:20 | access to indexer | access to indexer | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | $@ | CollectionFlow.cs:100:14:100:28 | call to method ListFirst | call to method ListFirst | +| CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:96:20:96:32 | object creation of type List : List | CollectionFlow.cs:212:63:212:69 | access to indexer | $@ | CollectionFlow.cs:212:63:212:69 | access to indexer | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:108:14:108:20 | access to indexer | $@ | CollectionFlow.cs:108:14:108:20 | access to indexer | access to indexer | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:105:17:105:23 | object creation of type A : A | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:108:14:108:20 | access to indexer | $@ | CollectionFlow.cs:108:14:108:20 | access to indexer | access to indexer | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:110:14:110:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:112:14:112:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:106:20:106:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:119:14:119:20 | access to indexer | $@ | CollectionFlow.cs:119:14:119:20 | access to indexer | access to indexer | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:121:14:121:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:123:14:123:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:117:20:117:43 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:130:14:130:20 | access to indexer | $@ | CollectionFlow.cs:130:14:130:20 | access to indexer | access to indexer | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:128:17:128:23 | object creation of type A : A | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:130:14:130:20 | access to indexer | $@ | CollectionFlow.cs:130:14:130:20 | access to indexer | access to indexer | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:132:14:132:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:134:14:134:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:129:20:129:56 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:140:14:140:20 | access to indexer | $@ | CollectionFlow.cs:140:14:140:20 | access to indexer | access to indexer | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | $@ | CollectionFlow.cs:142:14:142:32 | call to method DictIndexZero | call to method DictIndexZero | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | $@ | CollectionFlow.cs:144:14:144:34 | call to method DictValuesFirst | call to method DictValuesFirst | +| CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:139:20:139:60 | object creation of type Dictionary : Dictionary | CollectionFlow.cs:214:75:214:81 | access to indexer | $@ | CollectionFlow.cs:214:75:214:81 | access to indexer | access to indexer | +| CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:168:17:168:23 | object creation of type A : A | CollectionFlow.cs:171:18:171:18 | access to local variable x | $@ | CollectionFlow.cs:171:18:171:18 | access to local variable x | access to local variable x | +| CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:183:17:183:23 | object creation of type A : A | CollectionFlow.cs:187:18:187:35 | access to property Current | $@ | CollectionFlow.cs:187:18:187:35 | access to property Current | access to property Current | diff --git a/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.ql b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.ql new file mode 100644 index 00000000000..d1290562252 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/collections/CollectionFlow.ql @@ -0,0 +1,23 @@ +/** + * @kind path-problem + */ + +import csharp +import DataFlow::PathGraph + +class Conf extends TaintTracking::Configuration { + Conf() { this = "ArrayFlowConf" } + + override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ObjectCreation } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget().hasName("Sink") and + mc.getAnArgument() = sink.asExpr() + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, Conf conf +where conf.hasFlowPath(source, sink) +select source, source, sink, "$@", sink, sink.toString() diff --git a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql index 4015799bd1a..29281ffba56 100644 --- a/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql +++ b/csharp/ql/test/library-tests/dataflow/flowsources/remote/remoteFlowSource.ql @@ -1,4 +1,4 @@ -import semmle.code.csharp.dataflow.flowsources.Remote +import semmle.code.csharp.security.dataflow.flowsources.Remote from RemoteFlowSource source select source, source.getSourceType() diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected index 38c978be390..ca81fb55904 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlow.expected @@ -28,15 +28,15 @@ | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected deleted file mode 100644 index b386a148705..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.expected +++ /dev/null @@ -1,3816 +0,0 @@ -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg : String[] | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) : String | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) : String | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) : String | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 : String | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) : String | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) : String | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) : String | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 : String | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) : String | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) : String | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) : String | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg : String[] | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) : String | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) : String | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) : String | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 : String | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 : String | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) : String | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg : String[] | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted : String | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted : String | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) : String | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this : DataFlow | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this : DataFlow | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : T | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String[] | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String[] | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String[] | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : T | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String[] | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String[] | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String[] | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call : T | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this : DataFlow | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 : String | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this : DataFlow | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 : String | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this : DataFlow | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted : T | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this : DataFlow | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this : DataFlow | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this : DataFlow | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call : String | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this : DataFlow | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this : DataFlow | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : String | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : String | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : String | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : String | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : String | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : Object | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : String | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x : String | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return : T | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this : This | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this : This | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access : This | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this : Sub | diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql b/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql deleted file mode 100644 index d6d43ededd0..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowEdges.ql +++ /dev/null @@ -1,17 +0,0 @@ -import csharp -import DataFlow -import semmle.code.csharp.dataflow.internal.DataFlowPrivate - -class ConfigAny extends Configuration { - ConfigAny() { this = "ConfigAny" } - - override predicate isSource(Node source) { - source instanceof PostUpdateNode implies source.asExpr() instanceof ObjectCreation - } - - override predicate isSink(Node sink) { - sink instanceof PostUpdateNode implies sink.asExpr() instanceof ObjectCreation - } -} - -query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } diff --git a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected index cc1d49f3557..af0e92f2377 100644 --- a/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/DataFlowPath.expected @@ -75,7 +75,7 @@ edges | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | @@ -84,7 +84,7 @@ edges | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | @@ -100,31 +100,31 @@ edges | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:406:9:406:11 | value : String | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | @@ -151,36 +151,36 @@ edges | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -304,42 +304,42 @@ nodes | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -368,12 +368,12 @@ nodes | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | access to field SinkField0 | | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | access to local variable sink0 | | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | access to local variable sink1 | -| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | access to local variable sink2 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | access to local variable sink20 | -| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | | Capture.cs:12:19:12:24 | access to local variable sink27 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | access to local variable sink27 | | Capture.cs:21:23:21:28 | access to local variable sink28 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | access to local variable sink28 | | Capture.cs:30:19:30:24 | access to local variable sink29 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | access to local variable sink29 | @@ -390,20 +390,20 @@ nodes | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | access to local variable sink4 | | Capture.cs:122:15:122:20 | access to local variable sink40 | Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:122:15:122:20 | access to local variable sink40 | access to local variable sink40 | | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | access to local variable sink9 | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | | Splitting.cs:34:19:34:19 | access to local variable x | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | access to local variable x | | Capture.cs:57:27:57:32 | access to parameter sink39 | Capture.cs:7:20:7:26 | tainted : String | Capture.cs:57:27:57:32 | access to parameter sink39 | access to parameter sink39 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | | Splitting.cs:21:28:21:32 | access to parameter value | Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:21:28:21:32 | access to parameter value | access to parameter value | | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | access to property SinkProperty0 | diff --git a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected index 586a0ef9ca8..2b712d5c2f8 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected +++ b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected @@ -54,25 +54,25 @@ | GlobalDataFlow.cs:78:9:78:46 | call to method ReturnRef | ref | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | return | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | yield return | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select | return | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select | yield return | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:59:82:72 | call to method First | return | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip | return | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip | yield return | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:59:84:72 | call to method First | return | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip | return | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip | yield return | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:106:86:119 | call to method First | return | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:86:125:86:135 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | return | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | -| GlobalDataFlow.cs:88:43:88:61 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:64:88:69 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | return | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | -| GlobalDataFlow.cs:90:75:90:88 | call to method First | return | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:90:91:90:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:112:90:117 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | +| GlobalDataFlow.cs:80:22:80:93 | call to method First | return | GlobalDataFlow.cs:80:22:80:93 | call to method First | +| GlobalDataFlow.cs:82:22:82:87 | call to method Select | return | GlobalDataFlow.cs:82:22:82:87 | call to method Select | +| GlobalDataFlow.cs:82:22:82:87 | call to method Select | yield return | GlobalDataFlow.cs:82:22:82:87 | call to method Select | +| GlobalDataFlow.cs:82:22:82:95 | call to method First | return | GlobalDataFlow.cs:82:22:82:95 | call to method First | +| GlobalDataFlow.cs:82:76:82:86 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:84:22:84:128 | call to method Zip | return | GlobalDataFlow.cs:84:22:84:128 | call to method Zip | +| GlobalDataFlow.cs:84:22:84:128 | call to method Zip | yield return | GlobalDataFlow.cs:84:22:84:128 | call to method Zip | +| GlobalDataFlow.cs:84:22:84:136 | call to method First | return | GlobalDataFlow.cs:84:22:84:136 | call to method First | +| GlobalDataFlow.cs:84:117:84:127 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... | +| GlobalDataFlow.cs:86:22:86:128 | call to method Zip | return | GlobalDataFlow.cs:86:22:86:128 | call to method Zip | +| GlobalDataFlow.cs:86:22:86:128 | call to method Zip | yield return | GlobalDataFlow.cs:86:22:86:128 | call to method Zip | +| GlobalDataFlow.cs:86:22:86:136 | call to method First | return | GlobalDataFlow.cs:86:22:86:136 | call to method First | +| GlobalDataFlow.cs:86:117:86:127 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... | +| GlobalDataFlow.cs:88:22:88:110 | call to method Aggregate | return | GlobalDataFlow.cs:88:22:88:110 | call to method Aggregate | +| GlobalDataFlow.cs:88:83:88:101 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... | +| GlobalDataFlow.cs:88:104:88:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... | +| GlobalDataFlow.cs:90:22:90:110 | call to method Aggregate | return | GlobalDataFlow.cs:90:22:90:110 | call to method Aggregate | +| GlobalDataFlow.cs:90:83:90:101 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... | +| GlobalDataFlow.cs:90:104:90:109 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | out | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | ref | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | return | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | @@ -89,28 +89,30 @@ | GlobalDataFlow.cs:108:9:108:49 | call to method ReturnRef | ref | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | | GlobalDataFlow.cs:110:9:110:49 | call to method ReturnRef | out | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | | GlobalDataFlow.cs:110:9:110:49 | call to method ReturnRef | ref | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | return | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | yield return | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | return | GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | yield return | GlobalDataFlow.cs:112:20:112:86 | call to method SelectEven | +| GlobalDataFlow.cs:112:20:112:94 | call to method First | return | GlobalDataFlow.cs:112:20:112:94 | call to method First | | GlobalDataFlow.cs:114:20:114:82 | call to method Select | return | GlobalDataFlow.cs:114:20:114:82 | call to method Select | | GlobalDataFlow.cs:114:20:114:82 | call to method Select | yield return | GlobalDataFlow.cs:114:20:114:82 | call to method Select | +| GlobalDataFlow.cs:114:20:114:90 | call to method First | return | GlobalDataFlow.cs:114:20:114:90 | call to method First | | GlobalDataFlow.cs:114:76:114:81 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip | return | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip | yield return | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:57:116:70 | call to method First | return | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:116:123:116:133 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip | return | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip | yield return | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:104:118:117 | call to method First | return | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:118:123:118:133 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | return | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | -| GlobalDataFlow.cs:120:41:120:55 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:58:120:63 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | return | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | -| GlobalDataFlow.cs:122:41:122:59 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:62:122:68 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | return | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | -| GlobalDataFlow.cs:124:46:124:58 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:61:124:66 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | +| GlobalDataFlow.cs:116:20:116:126 | call to method Zip | return | GlobalDataFlow.cs:116:20:116:126 | call to method Zip | +| GlobalDataFlow.cs:116:20:116:126 | call to method Zip | yield return | GlobalDataFlow.cs:116:20:116:126 | call to method Zip | +| GlobalDataFlow.cs:116:20:116:134 | call to method First | return | GlobalDataFlow.cs:116:20:116:134 | call to method First | +| GlobalDataFlow.cs:116:115:116:125 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:116:115:116:125 | [output] (...) => ... | +| GlobalDataFlow.cs:118:20:118:126 | call to method Zip | return | GlobalDataFlow.cs:118:20:118:126 | call to method Zip | +| GlobalDataFlow.cs:118:20:118:126 | call to method Zip | yield return | GlobalDataFlow.cs:118:20:118:126 | call to method Zip | +| GlobalDataFlow.cs:118:20:118:134 | call to method First | return | GlobalDataFlow.cs:118:20:118:134 | call to method First | +| GlobalDataFlow.cs:118:115:118:125 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:118:115:118:125 | [output] (...) => ... | +| GlobalDataFlow.cs:120:20:120:104 | call to method Aggregate | return | GlobalDataFlow.cs:120:20:120:104 | call to method Aggregate | +| GlobalDataFlow.cs:120:81:120:95 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:81:120:95 | [output] (...) => ... | +| GlobalDataFlow.cs:120:98:120:103 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:120:98:120:103 | [output] (...) => ... | +| GlobalDataFlow.cs:122:20:122:109 | call to method Aggregate | return | GlobalDataFlow.cs:122:20:122:109 | call to method Aggregate | +| GlobalDataFlow.cs:122:81:122:99 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:81:122:99 | [output] (...) => ... | +| GlobalDataFlow.cs:122:102:122:108 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:122:102:122:108 | [output] (...) => ... | +| GlobalDataFlow.cs:124:20:124:107 | call to method Aggregate | return | GlobalDataFlow.cs:124:20:124:107 | call to method Aggregate | +| GlobalDataFlow.cs:124:86:124:98 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:86:124:98 | [output] (...) => ... | +| GlobalDataFlow.cs:124:101:124:106 | [implicit call] (...) => ... | return | GlobalDataFlow.cs:124:101:124:106 | [output] (...) => ... | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | out | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | ref | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | return | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | @@ -130,6 +132,7 @@ | GlobalDataFlow.cs:159:9:159:25 | call to method OutRef | ref | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | return | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | yield return | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | +| GlobalDataFlow.cs:161:22:161:39 | call to method First | return | GlobalDataFlow.cs:161:22:161:39 | call to method First | | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | return | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | return | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | | GlobalDataFlow.cs:169:9:169:31 | call to method NonOutOut | out | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | @@ -150,32 +153,42 @@ | GlobalDataFlow.cs:193:37:193:42 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | return | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | return | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | return | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select | return | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select | yield return | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:37:210:38 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | +| GlobalDataFlow.cs:207:38:207:75 | call to method AsQueryable | return | GlobalDataFlow.cs:207:38:207:75 | call to method AsQueryable | +| GlobalDataFlow.cs:208:41:208:77 | call to method AsQueryable | return | GlobalDataFlow.cs:208:41:208:77 | call to method AsQueryable | +| GlobalDataFlow.cs:211:76:211:90 | call to method ReturnCheck2 | return | GlobalDataFlow.cs:211:76:211:90 | call to method ReturnCheck2 | | GlobalDataFlow.cs:212:22:212:39 | call to method Select | return | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select | return | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select | yield return | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | return | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select | return | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select | yield return | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:41:220:42 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select | return | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | +| GlobalDataFlow.cs:212:22:212:39 | call to method Select | yield return | GlobalDataFlow.cs:212:22:212:39 | call to method Select | +| GlobalDataFlow.cs:212:22:212:47 | call to method First | return | GlobalDataFlow.cs:212:22:212:47 | call to method First | +| GlobalDataFlow.cs:212:37:212:38 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 | +| GlobalDataFlow.cs:214:22:214:39 | call to method Select | return | GlobalDataFlow.cs:214:22:214:39 | call to method Select | +| GlobalDataFlow.cs:214:22:214:47 | call to method First | return | GlobalDataFlow.cs:214:22:214:47 | call to method First | +| GlobalDataFlow.cs:214:37:214:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 | +| GlobalDataFlow.cs:216:22:216:49 | call to method Select | return | GlobalDataFlow.cs:216:22:216:49 | call to method Select | +| GlobalDataFlow.cs:216:22:216:49 | call to method Select | yield return | GlobalDataFlow.cs:216:22:216:49 | call to method Select | +| GlobalDataFlow.cs:216:22:216:57 | call to method First | return | GlobalDataFlow.cs:216:22:216:57 | call to method First | +| GlobalDataFlow.cs:216:37:216:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:221:76:221:92 | call to method NonReturnCheck | return | GlobalDataFlow.cs:221:76:221:92 | call to method NonReturnCheck | +| GlobalDataFlow.cs:222:23:222:43 | call to method Select | return | GlobalDataFlow.cs:222:23:222:43 | call to method Select | +| GlobalDataFlow.cs:222:23:222:43 | call to method Select | yield return | GlobalDataFlow.cs:222:23:222:43 | call to method Select | +| GlobalDataFlow.cs:222:23:222:51 | call to method First | return | GlobalDataFlow.cs:222:23:222:51 | call to method First | +| GlobalDataFlow.cs:222:41:222:42 | [implicit call] access to local variable f1 | return | GlobalDataFlow.cs:222:41:222:42 | [output] access to local variable f1 | | GlobalDataFlow.cs:224:19:224:39 | call to method Select | return | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select | yield return | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:37:224:38 | [implicit call] access to local variable f3 | return | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | +| GlobalDataFlow.cs:224:19:224:47 | call to method First | return | GlobalDataFlow.cs:224:19:224:47 | call to method First | +| GlobalDataFlow.cs:224:37:224:38 | [implicit call] access to local variable f2 | return | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f2 | | GlobalDataFlow.cs:226:19:226:39 | call to method Select | return | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [implicit call] access to local variable f4 | return | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select | return | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select | yield return | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call | return | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call | return | GlobalDataFlow.cs:431:44:431:47 | delegate call | +| GlobalDataFlow.cs:226:19:226:39 | call to method Select | yield return | GlobalDataFlow.cs:226:19:226:39 | call to method Select | +| GlobalDataFlow.cs:226:19:226:47 | call to method First | return | GlobalDataFlow.cs:226:19:226:47 | call to method First | +| GlobalDataFlow.cs:226:37:226:38 | [implicit call] access to local variable f3 | return | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f3 | +| GlobalDataFlow.cs:228:19:228:39 | call to method Select | return | GlobalDataFlow.cs:228:19:228:39 | call to method Select | +| GlobalDataFlow.cs:228:19:228:47 | call to method First | return | GlobalDataFlow.cs:228:19:228:47 | call to method First | +| GlobalDataFlow.cs:228:37:228:38 | [implicit call] access to local variable f4 | return | GlobalDataFlow.cs:228:37:228:38 | [output] access to local variable f4 | +| GlobalDataFlow.cs:230:19:230:49 | call to method Select | return | GlobalDataFlow.cs:230:19:230:49 | call to method Select | +| GlobalDataFlow.cs:230:19:230:49 | call to method Select | yield return | GlobalDataFlow.cs:230:19:230:49 | call to method Select | +| GlobalDataFlow.cs:230:19:230:57 | call to method First | return | GlobalDataFlow.cs:230:19:230:57 | call to method First | +| GlobalDataFlow.cs:230:37:230:48 | [implicit call] delegate creation of type Func | return | GlobalDataFlow.cs:230:37:230:48 | [output] delegate creation of type Func | +| GlobalDataFlow.cs:279:17:279:38 | call to method ApplyFunc | return | GlobalDataFlow.cs:279:17:279:38 | call to method ApplyFunc | +| GlobalDataFlow.cs:368:16:368:19 | delegate call | return | GlobalDataFlow.cs:368:16:368:19 | delegate call | +| GlobalDataFlow.cs:433:44:433:47 | delegate call | return | GlobalDataFlow.cs:433:44:433:47 | delegate call | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | return | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | | Splitting.cs:20:22:20:30 | call to method Return | return | Splitting.cs:20:22:20:30 | call to method Return | diff --git a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs index 41630b7fd8f..83003aaea66 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/global/GlobalDataFlow.cs @@ -77,17 +77,17 @@ public class DataFlow var sink3 = ""; ReturnRef(sink2, ref sink3, ref sink3); Check(sink3); - var sink13 = ((IEnumerable)new string[] { sink3 }).SelectEven(x => x); + var sink13 = ((IEnumerable)new string[] { sink3 }).SelectEven(x => x).First(); Check(sink13); - var sink14 = ((IEnumerable)new string[] { sink13.First() }).Select(ReturnCheck); + var sink14 = ((IEnumerable)new string[] { sink13 }).Select(ReturnCheck).First(); Check(sink14); - var sink15 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => x); + var sink15 = ((IEnumerable)new string[] { sink14 }).Zip(((IEnumerable)new string[] { "" }), (x, y) => x).First(); Check(sink15); - var sink16 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => y); + var sink16 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15 }), (x, y) => y).First(); Check(sink16); - var sink17 = sink14.Aggregate("", (acc, s) => acc + s, x => x); + var sink17 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc + s, x => x); Check(sink17); - var sink18 = ((IEnumerable)new string[] { "" }).Aggregate(sink14.First(), (acc, s) => acc + s, x => x); + var sink18 = ((IEnumerable)new string[] { "" }).Aggregate(sink14, (acc, s) => acc + s, x => x); Check(sink18); int sink21; Int32.TryParse(sink18, out sink21); @@ -109,19 +109,19 @@ public class DataFlow Check(nonSink0); ReturnRef(sink1, ref sink1, ref nonSink0); Check(nonSink0); - var nonSink1 = ((IEnumerable)new string[] { nonSink0 }).SelectEven(x => x); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { nonSink0 }).Select(x => x); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { sink14.First() }).Zip(((IEnumerable)new string[] { "" }), (x, y) => y); - Check(nonSink1); - nonSink1 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15.First() }), (x, y) => x); - Check(nonSink1); - nonSink0 = sink14.Aggregate("", (acc, s) => acc, x => x); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).SelectEven(x => x).First(); Check(nonSink0); - nonSink0 = sink14.Aggregate("", (acc, s) => acc + s, x => ""); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).Select(x => x).First(); Check(nonSink0); - nonSink0 = nonSink1.Aggregate(sink1, (acc, s) => s, x => x); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Zip(((IEnumerable)new string[] { "" }), (x, y) => y).First(); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { "" }).Zip(((IEnumerable)new string[] { sink15 }), (x, y) => x).First(); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc, x => x); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { sink14 }).Aggregate("", (acc, s) => acc + s, x => ""); + Check(nonSink0); + nonSink0 = ((IEnumerable)new string[] { nonSink0 }).Aggregate(sink1, (acc, s) => s, x => x); Check(nonSink0); int nonSink2; Int32.TryParse(nonSink0, out nonSink2); @@ -158,7 +158,7 @@ public class DataFlow var sink8 = ""; OutRef(ref sink8); Check(sink8); - var sink12 = OutYield(); + var sink12 = OutYield().First(); Check(sink12); var sink23 = TaintedParam(nonSink0); // even though the argument is not tainted, the parameter is considered tainted Check(sink23); @@ -202,30 +202,32 @@ public class DataFlow Check(nonSink0); } - public void M2(IQueryable tainted, IQueryable notTainted) + public void M2() { + IQueryable tainted = new[] { "taint source" }.AsQueryable(); + IQueryable notTainted = new[] { "not tainted" }.AsQueryable(); // Flow into a callable via library call, tainted Func f1 = sinkParam10 => { Check(sinkParam10); return sinkParam10; }; System.Linq.Expressions.Expression> f2 = x => ReturnCheck2(x); - var sink24 = tainted.Select(f1); + var sink24 = tainted.Select(f1).First(); Check(sink24); - var sink25 = tainted.Select(f2); + var sink25 = tainted.Select(f2).First(); Check(sink25); - var sink26 = tainted.Select(ReturnCheck3); + var sink26 = tainted.Select(ReturnCheck3).First(); Check(sink26); // Flow into a callable via library call, not tainted Func f3 = nonSinkParam => { Check(nonSinkParam); return nonSinkParam; }; System.Linq.Expressions.Expression> f4 = x => NonReturnCheck(x); - var nonSink = notTainted.Select(f1); + var nonSink = notTainted.Select(f1).First(); Check(nonSink); - nonSink = notTainted.Select(f2); + nonSink = notTainted.Select(f2).First(); Check(nonSink); - nonSink = notTainted.Select(f3); + nonSink = notTainted.Select(f3).First(); Check(nonSink); - nonSink = notTainted.Select(f4); + nonSink = notTainted.Select(f4).First(); Check(nonSink); - nonSink = notTainted.Select(ReturnCheck3); + nonSink = notTainted.Select(ReturnCheck3).First(); Check(nonSink); } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected index 10d873cc2fc..57fd2c9e0c3 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTracking.expected @@ -37,22 +37,22 @@ | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected deleted file mode 100644 index bd9d777b9dd..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.expected +++ /dev/null @@ -1,5782 +0,0 @@ -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:14:9:14:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:7:10:7:11 | this : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:7:20:7:26 | tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:7:20:7:26 | tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : Object | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:14:9:14:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:25:9:25:20 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:33:9:33:40 | [implicit argument] tainted : String | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted | -| Capture.cs:7:20:7:26 | tainted : String | Capture.cs:61:36:61:42 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:11:26:11:32 | access to parameter tainted : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:17:11:32 | SSA def(sink27) : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:11:17:11:32 | SSA def(sink27) : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:11:26:11:32 | access to parameter tainted : String | Capture.cs:12:19:12:24 | access to local variable sink27 : String | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:25:9:25:18 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:14:9:14:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) | -| Capture.cs:14:9:14:20 | [implicit argument] tainted : String | Capture.cs:9:9:13:9 | SSA capture def(tainted) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:20:30:20:36 | access to parameter tainted : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:21:20:36 | SSA def(sink28) : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:20:21:20:36 | SSA def(sink28) : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:20:30:20:36 | access to parameter tainted : String | Capture.cs:21:23:21:28 | access to local variable sink28 : String | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:49:9:49:27 | this access : Capture | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:25:9:25:18 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) | -| Capture.cs:25:9:25:20 | [implicit argument] tainted : String | Capture.cs:18:13:22:13 | SSA capture def(tainted) : String | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:27:43:27:45 | arg | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:27:43:27:45 | arg : String | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : Object | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:27:43:27:45 | arg : String | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:31:20:31:22 | access to parameter arg | -| Capture.cs:27:43:27:45 | arg : String[] | Capture.cs:31:20:31:22 | access to parameter arg : String | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:27:30:32:9 | SSA def(captureIn3) : Func | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 | -| Capture.cs:27:43:32:9 | (...) => ... : Func | Capture.cs:33:30:33:39 | access to local variable captureIn3 : Func | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:29:26:29:32 | access to parameter tainted : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:17:29:32 | SSA def(sink29) : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:29:17:29:32 | SSA def(sink29) : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:29:26:29:32 | access to parameter tainted : String | Capture.cs:30:19:30:24 | access to local variable sink29 : String | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:31:20:31:22 | access to parameter arg : String | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:27:43:27:45 | arg : String[] | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 | -| Capture.cs:33:9:33:21 | array creation of type String[] : String[] | Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) | -| Capture.cs:33:9:33:40 | [implicit argument] tainted : String | Capture.cs:27:43:32:9 | SSA capture def(tainted) : String | -| Capture.cs:33:9:33:40 | call to method Select : IEnumerable | Capture.cs:33:9:33:50 | call to method ToArray | -| Capture.cs:33:9:33:40 | call to method Select : IEnumerable | Capture.cs:33:9:33:50 | call to method ToArray : String[] | -| Capture.cs:33:17:33:19 | " " : String | Capture.cs:33:9:33:21 | array creation of type String[] | -| Capture.cs:33:17:33:19 | " " : String | Capture.cs:33:9:33:21 | array creation of type String[] : String[] | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:40 | call to method Select | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:40 | call to method Select : IEnumerable | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:50 | call to method ToArray | -| Capture.cs:33:30:33:39 | [output] access to local variable captureIn3 : String | Capture.cs:33:9:33:50 | call to method ToArray : String[] | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:37:28:37:34 | access to parameter tainted : String | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:35:9:39:9 | SSA capture def(tainted) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:37:17:37:34 | SSA def(nonSink0) : String | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 | -| Capture.cs:37:28:37:34 | access to parameter tainted : String | Capture.cs:38:19:38:26 | access to local variable nonSink0 : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:45:32:45:38 | access to parameter tainted : String | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:43:13:47:13 | SSA capture def(tainted) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:45:21:45:38 | SSA def(nonSink0) : String | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 | -| Capture.cs:45:32:45:38 | access to parameter tainted : String | Capture.cs:46:23:46:30 | access to local variable nonSink0 : String | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access | -| Capture.cs:49:9:49:27 | this access : Capture | Capture.cs:61:9:61:19 | this access : Capture | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : Object | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:33:50:40 | nonSink0 : String | Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : Object | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:50:50:50:55 | sink39 : String | Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] nonSink0 : String | Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:13:59:14 | [implicit argument] sink39 : String | Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:52:23:59:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:52:23:59:13 | SSA capture def(nonSink0) : String | Capture.cs:54:23:54:30 | access to parameter nonSink0 : String | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:55:27:58:17 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:55:27:58:17 | SSA capture def(sink39) : String | Capture.cs:57:27:57:32 | access to parameter sink39 : String | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 | -| Capture.cs:61:21:61:33 | "not tainted" : String | Capture.cs:50:33:50:40 | nonSink0 : String | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 | -| Capture.cs:61:36:61:42 | access to parameter tainted : String | Capture.cs:50:50:50:55 | sink39 : String | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:71:9:71:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:64:10:64:12 | this : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) | -| Capture.cs:66:25:66:26 | "" : String | Capture.cs:66:16:66:26 | SSA def(sink30) : String | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) | -| Capture.cs:69:13:69:35 | SSA def(sink30) : String | Capture.cs:71:9:71:21 | SSA call def(sink30) : String | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) | -| Capture.cs:69:22:69:35 | "taint source" : String | Capture.cs:69:13:69:35 | SSA def(sink30) : String | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:83:9:83:19 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:71:9:71:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 | -| Capture.cs:71:9:71:21 | SSA call def(sink30) : String | Capture.cs:72:15:72:20 | access to local variable sink30 : String | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) | -| Capture.cs:74:25:74:26 | "" : String | Capture.cs:74:16:74:26 | SSA def(sink31) : String | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) | -| Capture.cs:79:17:79:39 | SSA def(sink31) : String | Capture.cs:83:9:83:21 | SSA call def(sink31) : String | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) | -| Capture.cs:79:26:79:39 | "taint source" : String | Capture.cs:79:17:79:39 | SSA def(sink31) : String | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:109:9:109:28 | this access : Capture | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:83:9:83:19 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 | -| Capture.cs:83:9:83:21 | SSA call def(sink31) : String | Capture.cs:84:15:84:20 | access to local variable sink31 : String | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) | -| Capture.cs:86:25:86:26 | "" : String | Capture.cs:86:16:86:26 | SSA def(sink32) : String | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:87:44:87:46 | arg | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:87:44:87:46 | arg : String | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : Object | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:87:44:87:46 | arg : String | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:90:20:90:22 | access to parameter arg | -| Capture.cs:87:44:87:46 | arg : String[] | Capture.cs:90:20:90:22 | access to parameter arg : String | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:87:30:91:9 | SSA def(captureOut3) : Func | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 | -| Capture.cs:87:44:91:9 | (...) => ... : Func | Capture.cs:92:30:92:40 | access to local variable captureOut3 : Func | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) | -| Capture.cs:89:13:89:35 | SSA def(sink32) : String | Capture.cs:92:9:92:41 | SSA call def(sink32) : String | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) | -| Capture.cs:89:22:89:35 | "taint source" : String | Capture.cs:89:13:89:35 | SSA def(sink32) : String | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:90:20:90:22 | access to parameter arg : String | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:87:44:87:46 | arg : String[] | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 | -| Capture.cs:92:9:92:21 | array creation of type String[] : String[] | Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 | -| Capture.cs:92:9:92:41 | SSA call def(sink32) : String | Capture.cs:93:15:93:20 | access to local variable sink32 : String | -| Capture.cs:92:9:92:41 | call to method Select : IEnumerable | Capture.cs:92:9:92:51 | call to method ToArray | -| Capture.cs:92:9:92:41 | call to method Select : IEnumerable | Capture.cs:92:9:92:51 | call to method ToArray : String[] | -| Capture.cs:92:17:92:19 | " " : String | Capture.cs:92:9:92:21 | array creation of type String[] | -| Capture.cs:92:17:92:19 | " " : String | Capture.cs:92:9:92:21 | array creation of type String[] : String[] | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:41 | call to method Select | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:41 | call to method Select : IEnumerable | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:51 | call to method ToArray | -| Capture.cs:92:30:92:40 | [output] access to local variable captureOut3 : String | Capture.cs:92:9:92:51 | call to method ToArray : String[] | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:95:16:95:28 | SSA def(nonSink0) : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:95:27:95:28 | "" : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 | -| Capture.cs:100:15:100:22 | access to local variable nonSink0 : String | Capture.cs:110:15:110:22 | access to local variable nonSink0 : String | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access | -| Capture.cs:109:9:109:28 | this access : Capture | Capture.cs:121:9:121:33 | this access : Capture | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) | -| Capture.cs:111:25:111:26 | "" : String | Capture.cs:111:16:111:26 | SSA def(sink40) : String | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:114:23:116:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) | -| Capture.cs:115:17:115:39 | SSA def(sink40) : String | Capture.cs:121:9:121:35 | SSA call def(sink40) : String | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) | -| Capture.cs:115:26:115:39 | "taint source" : String | Capture.cs:115:17:115:39 | SSA def(sink40) : String | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a | -| Capture.cs:117:23:119:13 | (...) => ... : Action | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) | -| Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) | -| Capture.cs:118:28:118:40 | "not tainted" : String | Capture.cs:118:17:118:40 | SSA def(nonSink0) : String | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 | -| Capture.cs:121:9:121:35 | SSA call def(nonSink0) : String | Capture.cs:122:30:122:37 | access to local variable nonSink0 : String | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 | -| Capture.cs:121:9:121:35 | SSA call def(sink40) : String | Capture.cs:122:15:122:20 | access to local variable sink40 : String | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:132:9:132:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:125:10:125:16 | this : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:125:25:125:31 | tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:125:25:125:31 | tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : Object | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:132:9:132:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:144:9:144:25 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:153:9:153:45 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:160:22:160:38 | [implicit argument] tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:168:25:168:31 | access to parameter tainted : String | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:125:25:125:31 | tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) | -| Capture.cs:127:25:127:26 | "" : String | Capture.cs:127:16:127:26 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | Capture.cs:130:22:130:28 | access to parameter tainted : String | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:130:13:130:28 | SSA def(sink33) : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:130:22:130:28 | access to parameter tainted : String | Capture.cs:130:13:130:28 | SSA def(sink33) : String | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:144:9:144:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:132:9:132:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 | -| Capture.cs:132:9:132:25 | SSA call def(sink33) : String | Capture.cs:133:15:133:20 | access to local variable sink33 : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:128:9:131:9 | SSA capture def(tainted) : String | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) | -| Capture.cs:132:9:132:25 | [implicit argument] tainted : String | Capture.cs:132:9:132:25 | SSA call def(sink33) : String | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) | -| Capture.cs:135:25:135:26 | "" : String | Capture.cs:135:16:135:26 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | Capture.cs:140:26:140:32 | access to parameter tainted : String | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:140:17:140:32 | SSA def(sink34) : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:140:26:140:32 | access to parameter tainted : String | Capture.cs:140:17:140:32 | SSA def(sink34) : String | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:160:22:160:36 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:144:9:144:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 | -| Capture.cs:144:9:144:25 | SSA call def(sink34) : String | Capture.cs:145:15:145:20 | access to local variable sink34 : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:138:13:141:13 | SSA capture def(tainted) : String | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) | -| Capture.cs:144:9:144:25 | [implicit argument] tainted : String | Capture.cs:144:9:144:25 | SSA call def(sink34) : String | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) | -| Capture.cs:147:25:147:26 | "" : String | Capture.cs:147:16:147:26 | SSA def(sink35) : String | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:148:48:148:50 | arg | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:148:48:148:50 | arg : String | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : Object | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:148:48:148:50 | arg : String | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:151:20:151:22 | access to parameter arg | -| Capture.cs:148:48:148:50 | arg : String[] | Capture.cs:151:20:151:22 | access to parameter arg : String | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:148:30:152:9 | SSA def(captureThrough3) : Func | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 | -| Capture.cs:148:48:152:9 | (...) => ... : Func | Capture.cs:153:30:153:44 | access to local variable captureThrough3 : Func | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | Capture.cs:150:22:150:28 | access to parameter tainted : String | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:150:13:150:28 | SSA def(sink35) : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:150:22:150:28 | access to parameter tainted : String | Capture.cs:150:13:150:28 | SSA def(sink35) : String | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:151:20:151:22 | access to parameter arg : String | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:148:48:148:50 | arg : String[] | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 | -| Capture.cs:153:9:153:21 | array creation of type String[] : String[] | Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 | -| Capture.cs:153:9:153:45 | SSA call def(sink35) : String | Capture.cs:154:15:154:20 | access to local variable sink35 : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:148:48:152:9 | SSA capture def(tainted) : String | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) | -| Capture.cs:153:9:153:45 | [implicit argument] tainted : String | Capture.cs:153:9:153:45 | SSA call def(sink35) : String | -| Capture.cs:153:9:153:45 | call to method Select : IEnumerable | Capture.cs:153:9:153:55 | call to method ToArray | -| Capture.cs:153:9:153:45 | call to method Select : IEnumerable | Capture.cs:153:9:153:55 | call to method ToArray : String[] | -| Capture.cs:153:17:153:19 | " " : String | Capture.cs:153:9:153:21 | array creation of type String[] | -| Capture.cs:153:17:153:19 | " " : String | Capture.cs:153:9:153:21 | array creation of type String[] : String[] | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:45 | call to method Select | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:45 | call to method Select : IEnumerable | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:55 | call to method ToArray | -| Capture.cs:153:30:153:44 | [output] access to local variable captureThrough3 : String | Capture.cs:153:9:153:55 | call to method ToArray : String[] | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | Capture.cs:158:20:158:26 | access to parameter tainted : String | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:158:20:158:26 | access to parameter tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:13:160:38 | SSA def(sink36) : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:168:9:168:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:160:22:160:36 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:156:9:159:9 | SSA capture def(tainted) : String | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 | -| Capture.cs:160:22:160:38 | [implicit argument] tainted : String | Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:160:13:160:38 | SSA def(sink36) : String | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 | -| Capture.cs:160:22:160:38 | call to local function CaptureThrough4 : String | Capture.cs:161:15:161:20 | access to local variable sink36 : String | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) | -| Capture.cs:163:22:163:23 | "" : String | Capture.cs:163:13:163:23 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:164:37:164:37 | p | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : Object | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:164:37:164:37 | p : String | Capture.cs:166:22:166:22 | access to parameter p : String | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:166:13:166:22 | SSA def(sink37) : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:166:22:166:22 | access to parameter p : String | Capture.cs:166:13:166:22 | SSA def(sink37) : String | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:185:9:185:32 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:168:9:168:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 | -| Capture.cs:168:9:168:32 | SSA call def(sink37) : String | Capture.cs:169:15:169:20 | access to local variable sink37 : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:164:37:164:37 | p : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:168:9:168:32 | SSA call def(sink37) : String | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted | -| Capture.cs:168:25:168:31 | access to parameter tainted : String | Capture.cs:194:25:194:31 | access to parameter tainted : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:171:16:171:28 | SSA def(nonSink0) : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:171:27:171:28 | "" : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted | -| Capture.cs:172:9:175:9 | SSA capture def(tainted) : String | Capture.cs:174:24:174:30 | access to parameter tainted : String | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 | -| Capture.cs:176:15:176:22 | access to local variable nonSink0 : String | Capture.cs:186:15:186:22 | access to local variable nonSink0 : String | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted | -| Capture.cs:180:13:183:13 | SSA capture def(tainted) : String | Capture.cs:182:28:182:34 | access to parameter tainted : String | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:194:22:194:23 | this access : Capture | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:185:9:185:32 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:188:26:188:26 | s | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : Object | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:188:26:188:26 | s : String | Capture.cs:191:20:191:22 | [implicit argument] s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:13:190:28 | SSA capture def(s) : String | Capture.cs:190:27:190:27 | access to parameter s : String | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:190:27:190:27 | access to parameter s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:190:13:190:28 | SSA capture def(s) : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | [implicit argument] s : String | Capture.cs:191:20:191:22 | call to local function M : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:191:20:191:22 | call to local function M : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:13:194:32 | SSA def(sink38) : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access | -| Capture.cs:194:22:194:23 | this access : Capture | Capture.cs:196:20:196:21 | this access : Capture | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:194:13:194:32 | SSA def(sink38) : String | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 | -| Capture.cs:194:22:194:32 | call to local function Id : String | Capture.cs:195:15:195:20 | access to local variable sink38 : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id | -| Capture.cs:194:25:194:31 | access to parameter tainted : String | Capture.cs:194:22:194:32 | call to local function Id : String | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:196:9:196:25 | SSA def(nonSink0) : String | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 | -| Capture.cs:196:20:196:25 | call to local function Id : String | Capture.cs:197:15:197:22 | access to local variable nonSink0 : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:188:26:188:26 | s : String | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id | -| Capture.cs:196:23:196:24 | "" : String | Capture.cs:196:20:196:25 | call to local function Id : String | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Action | Capture.cs:204:9:204:9 | access to parameter a : Action | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:202:34:202:34 | a | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:202:34:202:34 | a : Action | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:204:9:204:9 | access to parameter a | -| Capture.cs:202:34:202:34 | a : Object | Capture.cs:204:9:204:9 | access to parameter a : Action | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:14:17:14:17 | this : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:17:9:17:40 | SSA def(DataFlow.Test.SinkField0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:18:15:18:29 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:21:9:21:42 | SSA def(DataFlow.Test.NonSinkField0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:21:30:21:42 | "not tainted" : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:22:15:22:32 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:25:9:25:44 | SSA def(DataFlow.Test.SinkProperty0) : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:31:33:31:47 | access to field SinkField0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:25:30:25:44 | access to field SinkField0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:26:15:26:32 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:29:9:29:50 | SSA def(DataFlow.Test.NonSinkProperty0) : String | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 | -| GlobalDataFlow.cs:29:33:29:50 | access to field NonSinkField0 : String | GlobalDataFlow.cs:30:15:30:35 | access to property NonSinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:36:13:36:58 | SSA def(methodInfo) : MethodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo | -| GlobalDataFlow.cs:36:26:36:58 | call to method GetMethod : MethodInfo | GlobalDataFlow.cs:38:9:38:18 | access to local variable methodInfo : MethodInfo | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:13:37:54 | SSA def(args) : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:37:20:37:54 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:38:33:38:36 | access to local variable args : Object[] | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:41:16:41:17 | "" : String | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : Object | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 : String | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:44:24:44:60 | SSA def(in2) : Action | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 | -| GlobalDataFlow.cs:44:30:44:60 | (...) => ... : Action | GlobalDataFlow.cs:45:9:45:11 | access to local variable in2 : Action | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : Object | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | GlobalDataFlow.cs:48:56:48:68 | access to parameter nonSinkParam1 : String | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:48:24:48:69 | SSA def(nonIn1) : Action | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 | -| GlobalDataFlow.cs:48:33:48:69 | (...) => ... : Action | GlobalDataFlow.cs:49:9:49:14 | access to local variable nonIn1 : Action | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 | -| GlobalDataFlow.cs:49:16:49:17 | "" : String | GlobalDataFlow.cs:48:33:48:45 | nonSinkParam1 : String | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:52:15:52:17 | delegate creation of type Action : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : Object | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x | -| GlobalDataFlow.cs:53:15:53:15 | x : T | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:53:15:53:25 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : T | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:54:23:54:41 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:55:23:55:25 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:56:9:56:48 | SSA def(DataFlow.myDelegate) : MyDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate | -| GlobalDataFlow.cs:56:22:56:48 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : Object | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:57:23:57:32 | access to field myDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : Object | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | GlobalDataFlow.cs:60:38:60:50 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:60:15:60:51 | (...) => ... : Action | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:60:54:60:66 | "not tainted" : String | GlobalDataFlow.cs:359:41:359:41 | x : String | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:61:23:61:75 | delegate creation of type MyDelegate : MyDelegate | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : Object | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | GlobalDataFlow.cs:61:61:61:73 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:61:78:61:90 | "not tainted" : String | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this | -| GlobalDataFlow.cs:64:9:64:18 | this access : DataFlow | GlobalDataFlow.cs:404:9:404:11 | this : DataFlow | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this | -| GlobalDataFlow.cs:67:9:67:21 | this access : DataFlow | GlobalDataFlow.cs:410:9:410:11 | this : DataFlow | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:67:25:67:37 | "not tainted" : String | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:70:13:70:46 | SSA def(sink0) : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 | -| GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 : T | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:72:13:72:101 | SSA def(sink1) : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : Object | GlobalDataFlow.cs:72:21:72:101 | (...) ... : Object | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | GlobalDataFlow.cs:72:21:72:101 | (...) ... : String | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... | -| GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | GlobalDataFlow.cs:72:21:72:101 | (...) ... : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:72:79:72:100 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:73:15:73:19 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:75:19:75:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : String | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 | -| GlobalDataFlow.cs:76:15:76:19 | access to local variable sink2 : T | GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:77:13:77:22 | SSA def(sink3) : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:77:21:77:22 | "" : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:78:19:78:23 | access to local variable sink2 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 | -| GlobalDataFlow.cs:78:30:78:34 | access to local variable sink3 : String | GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:78:41:78:45 | access to local variable sink3 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:79:15:79:19 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:80:13:80:85 | SSA def(sink13) : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:80:44:80:65 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 | -| GlobalDataFlow.cs:80:59:80:63 | access to local variable sink3 : T | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:79:80:79 | x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : Object | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : String | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x | -| GlobalDataFlow.cs:80:79:80:79 | x : T | GlobalDataFlow.cs:80:84:80:84 | access to parameter x : T | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:80:79:80:84 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:80:84:80:84 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First | -| GlobalDataFlow.cs:82:59:82:64 | access to local variable sink13 : IEnumerable | GlobalDataFlow.cs:82:59:82:72 | call to method First : String | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:23:82:74 | (...) ... | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:59:82:72 | call to method First : String | GlobalDataFlow.cs:82:44:82:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:13:82:95 | SSA def(sink14) : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:22:82:95 | call to method Select | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:82:22:82:95 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String[] | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:84:59:84:72 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:84:59:84:64 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] | -| GlobalDataFlow.cs:84:59:84:72 | call to method First : String | GlobalDataFlow.cs:84:44:84:74 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:82:84:121 | (...) ... | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:82:84:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:118:84:119 | "" : String | GlobalDataFlow.cs:84:103:84:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:13:84:136 | SSA def(sink15) : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:22:84:136 | call to method Zip | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:84:22:84:136 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : IEnumerable | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : Object | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:126:84:126 | x | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:126:84:126 | x : String | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:135:84:135 | access to parameter x | -| GlobalDataFlow.cs:84:126:84:126 | x : String[] | GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... | -| GlobalDataFlow.cs:84:135:84:135 | access to parameter x : String | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:23:86:62 | (...) ... | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:23:86:62 | (...) ... : String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] | -| GlobalDataFlow.cs:86:59:86:60 | "" : String | GlobalDataFlow.cs:86:44:86:62 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String[] | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:86:106:86:119 | call to method First : String | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:86:106:86:111 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] | -| GlobalDataFlow.cs:86:106:86:119 | call to method First : String | GlobalDataFlow.cs:86:91:86:121 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:13:86:136 | SSA def(sink16) : IEnumerable | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:22:86:136 | call to method Zip | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:22:86:136 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 : IEnumerable | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : IEnumerable | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : Object | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:129:86:129 | y | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:129:86:129 | y : String | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:135:86:135 | access to parameter y | -| GlobalDataFlow.cs:86:129:86:129 | y : String[] | GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... | -| GlobalDataFlow.cs:86:135:86:135 | access to parameter y : String | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:39:88:40 | "" : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:44:88:46 | acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:44:88:46 | acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:44:88:46 | acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:49:88:49 | s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : IEnumerable | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:49:88:49 | s | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:49:88:49 | s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : Object | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:49:88:49 | s : String | GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:55:88:57 | access to parameter acc : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... | -| GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:61:88:61 | access to parameter s : String | GlobalDataFlow.cs:88:55:88:61 | ... + ... : String | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : Object | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:64:88:64 | x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:64:88:64 | x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:64 | x : String | GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:13:88:70 | SSA def(sink17) : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:88:22:88:70 | call to method Aggregate : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 : String | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... | -| GlobalDataFlow.cs:88:69:88:69 | access to parameter x : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String[] | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:23:90:62 | (...) ... | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:23:90:62 | (...) ... : String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] | -| GlobalDataFlow.cs:90:59:90:60 | "" : String | GlobalDataFlow.cs:90:44:90:62 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:92:90:94 | acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:92:90:94 | acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:92:90:94 | acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : IEnumerable | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : Object | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:97:90:97 | s | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:97:90:97 | s : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:109:90:109 | access to parameter s | -| GlobalDataFlow.cs:90:97:90:97 | s : String[] | GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:103:90:105 | access to parameter acc : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... | -| GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:109:90:109 | access to parameter s : String | GlobalDataFlow.cs:90:103:90:109 | ... + ... : String | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : Object | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:112:90:112 | x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:112:90:112 | x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:112 | x : String | GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:13:90:118 | SSA def(sink18) : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:90:22:90:118 | call to method Aggregate : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... | -| GlobalDataFlow.cs:90:117:90:117 | access to parameter x : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:9:93:42 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:93:24:93:29 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:93:36:93:41 | SSA def(sink21) : Int32 | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 : Int32 | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:9:96:41 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:23:96:28 | access to local variable sink18 : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | -| GlobalDataFlow.cs:96:35:96:40 | SSA def(sink22) : Boolean | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 : Boolean | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:100:13:100:33 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:100:24:100:33 | call to method Return : String | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:100:31:100:32 | "" : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 | -| GlobalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : Object | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:102:9:102:103 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | GlobalDataFlow.cs:103:15:103:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : Object | GlobalDataFlow.cs:102:20:102:103 | (...) ... : Object | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | GlobalDataFlow.cs:102:20:102:103 | (...) ... : String | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... | -| GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | GlobalDataFlow.cs:102:20:102:103 | (...) ... : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:102:78:102:102 | array creation of type Object[] : Object[] | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:102:93:102:100 | access to local variable nonSink0 : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:104:19:104:20 | "" : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:105:15:105:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:281:32:281:32 | x : Object | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : String | GlobalDataFlow.cs:281:32:281:32 | x : String | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:106:19:106:23 | access to local variable sink1 : T | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:107:15:107:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:108:19:108:20 | "" : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : String | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:108:27:108:34 | access to local variable nonSink0 : T | GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:108:41:108:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:109:15:109:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : Object | GlobalDataFlow.cs:287:32:287:32 | x : Object | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : String | GlobalDataFlow.cs:287:32:287:32 | x : String | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:110:30:110:34 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:110:19:110:23 | access to local variable sink1 : T | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : Object | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : Object | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : String | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : String | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 | -| GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | GlobalDataFlow.cs:124:39:124:43 | access to local variable sink1 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : String | GlobalDataFlow.cs:287:50:287:50 | z : String | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:110:41:110:48 | access to local variable nonSink0 : T | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:111:15:111:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:112:13:112:90 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:113:15:113:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : IEnumerable | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | GlobalDataFlow.cs:426:71:426:71 | e : String[] | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:25:112:70 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:112:46:112:70 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 | -| GlobalDataFlow.cs:112:61:112:68 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:84:112:84 | x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : Object | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : String | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x | -| GlobalDataFlow.cs:112:84:112:84 | x : T | GlobalDataFlow.cs:112:89:112:89 | access to parameter x : T | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:112:84:112:89 | (...) => ... : Func | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:112:89:112:89 | access to parameter x : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : String | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : IEnumerable | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String[] | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : String | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:21:114:66 | (...) ... : String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] | -| GlobalDataFlow.cs:114:57:114:64 | access to local variable nonSink0 : T | GlobalDataFlow.cs:114:42:114:66 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : IEnumerable | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : Object | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:76:114:76 | x | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:76:114:76 | x : String | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:81:114:81 | access to parameter x | -| GlobalDataFlow.cs:114:76:114:76 | x : String[] | GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:9:114:82 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:20:114:82 | call to method Select | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:114:20:114:82 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | GlobalDataFlow.cs:115:15:115:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... | -| GlobalDataFlow.cs:114:81:114:81 | access to parameter x : String | GlobalDataFlow.cs:114:76:114:81 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:116:57:116:70 | call to method First : String | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:116:57:116:62 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:21:116:72 | (...) ... : String[] | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] | -| GlobalDataFlow.cs:116:57:116:70 | call to method First : String | GlobalDataFlow.cs:116:42:116:72 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String[] | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:80:116:119 | (...) ... | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:80:116:119 | (...) ... : String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] | -| GlobalDataFlow.cs:116:116:116:117 | "" : String | GlobalDataFlow.cs:116:101:116:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:9:116:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:20:116:134 | call to method Zip | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:116:20:116:134 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | GlobalDataFlow.cs:117:15:117:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : IEnumerable | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : Object | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:127:116:127 | y | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:127:116:127 | y : String | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:133:116:133 | access to parameter y | -| GlobalDataFlow.cs:116:127:116:127 | y : String[] | GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... | -| GlobalDataFlow.cs:116:133:116:133 | access to parameter y : String | GlobalDataFlow.cs:116:123:116:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String[] | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:21:118:60 | (...) ... | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:21:118:60 | (...) ... : String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] | -| GlobalDataFlow.cs:118:57:118:58 | "" : String | GlobalDataFlow.cs:118:42:118:60 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First | -| GlobalDataFlow.cs:118:104:118:109 | access to local variable sink15 : IEnumerable | GlobalDataFlow.cs:118:104:118:117 | call to method First : String | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:68:118:119 | (...) ... : String[] | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] | -| GlobalDataFlow.cs:118:104:118:117 | call to method First : String | GlobalDataFlow.cs:118:89:118:119 | array creation of type String[] : String[] | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:9:118:134 | SSA def(nonSink1) : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:20:118:134 | call to method Zip | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:118:20:118:134 | call to method Zip : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : IEnumerable | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : Object | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:124:118:124 | x | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:124:118:124 | x : String | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:133:118:133 | access to parameter x | -| GlobalDataFlow.cs:118:124:118:124 | x : String[] | GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... | -| GlobalDataFlow.cs:118:133:118:133 | access to parameter x : String | GlobalDataFlow.cs:118:123:118:133 | [output] (...) => ... : String | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 | -| GlobalDataFlow.cs:119:15:119:22 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 | -| GlobalDataFlow.cs:120:20:120:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:37:120:38 | "" : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : Object | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:42:120:44 | acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:42:120:44 | acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:42:120:44 | acc : String | GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... | -| GlobalDataFlow.cs:120:53:120:55 | access to parameter acc : String | GlobalDataFlow.cs:120:41:120:55 | [output] (...) => ... : String | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : Object | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:58:120:58 | x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:58:120:58 | x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:58 | x : String | GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:9:120:64 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:120:20:120:64 | call to method Aggregate : String | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | GlobalDataFlow.cs:121:15:121:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... | -| GlobalDataFlow.cs:120:63:120:63 | access to parameter x : String | GlobalDataFlow.cs:120:58:120:63 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:20:122:25 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:37:122:38 | "" : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:42:122:44 | acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:42:122:44 | acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:42:122:44 | acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:47:122:47 | s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : IEnumerable | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:47:122:47 | s | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:47:122:47 | s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : Object | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:47:122:47 | s : String | GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:53:122:55 | access to parameter acc : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... | -| GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | GlobalDataFlow.cs:122:41:122:59 | [output] (...) => ... : String | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:59:122:59 | access to parameter s : String | GlobalDataFlow.cs:122:53:122:59 | ... + ... : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:9:122:69 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:122:20:122:69 | call to method Aggregate : String | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | GlobalDataFlow.cs:123:15:123:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... | -| GlobalDataFlow.cs:122:67:122:68 | "" : String | GlobalDataFlow.cs:122:62:122:68 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:20:124:27 | access to local variable nonSink1 : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:52:124:52 | s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : IEnumerable | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:52:124:52 | s | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:52:124:52 | s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : Object | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:52:124:52 | s : String | GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... | -| GlobalDataFlow.cs:124:58:124:58 | access to parameter s : String | GlobalDataFlow.cs:124:46:124:58 | [output] (...) => ... : String | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : Object | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:61:124:61 | x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:61:124:61 | x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:61 | x : String | GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:9:124:67 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:124:20:124:67 | call to method Aggregate : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... | -| GlobalDataFlow.cs:124:66:124:66 | access to parameter x : String | GlobalDataFlow.cs:124:61:124:66 | [output] (...) => ... : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:125:15:125:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:9:127:46 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:127:24:127:31 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 | -| GlobalDataFlow.cs:127:38:127:45 | SSA def(nonSink2) : Int32 | GlobalDataFlow.cs:128:15:128:22 | access to local variable nonSink2 : Int32 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:9:130:45 | call to method TryParse : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 | -| GlobalDataFlow.cs:130:23:130:30 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 | -| GlobalDataFlow.cs:130:37:130:44 | SSA def(nonSink3) : Boolean | GlobalDataFlow.cs:131:15:131:22 | access to local variable nonSink3 : Boolean | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | -| GlobalDataFlow.cs:134:40:134:40 | x : Object | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : String | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x | -| GlobalDataFlow.cs:134:40:134:40 | x : T | GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:134:30:134:64 | SSA def(return) : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:134:40:134:64 | (...) => ... : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | GlobalDataFlow.cs:139:20:139:36 | delegate call : T | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:134:55:134:60 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:134:63:134:63 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return | -| GlobalDataFlow.cs:135:21:135:27 | access to local variable return : Func | GlobalDataFlow.cs:139:20:139:26 | access to local variable return : Func | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:135:13:135:34 | SSA def(sink4) : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:135:21:135:34 | delegate call : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:134:40:134:40 | x : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : Object | GlobalDataFlow.cs:135:21:135:34 | delegate call : Object | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:134:40:134:40 | x : T | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call | -| GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : T | GlobalDataFlow.cs:135:21:135:34 | delegate call : T | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 | -| GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 : T | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : String | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:139:9:139:36 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:139:20:139:36 | delegate call : T | GlobalDataFlow.cs:140:15:140:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:134:40:134:40 | x : String | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call | -| GlobalDataFlow.cs:139:28:139:35 | access to local variable nonSink0 : String | GlobalDataFlow.cs:139:20:139:36 | delegate call : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:143:13:143:44 | SSA def(sink5) : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:143:31:143:36 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : Object | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : String | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 | -| GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 : T | GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:147:9:147:40 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | GlobalDataFlow.cs:148:15:148:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:147:30:147:35 | delegate creation of type Func : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:147:38:147:39 | "" : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:149:9:149:44 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:149:30:149:36 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:149:35:149:36 | "" : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:149:39:149:43 | access to local variable sink5 : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 | -| GlobalDataFlow.cs:150:15:150:22 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:153:13:153:25 | SSA def(sink6) : String | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | -| GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 : String | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this | -| GlobalDataFlow.cs:153:21:153:25 | this access : DataFlow | GlobalDataFlow.cs:316:12:316:14 | this : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this | -| GlobalDataFlow.cs:156:9:156:25 | this access : DataFlow | GlobalDataFlow.cs:321:10:321:15 | this : DataFlow | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | -| GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 : String | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:158:13:158:22 | SSA def(sink8) : String | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 | -| GlobalDataFlow.cs:158:21:158:22 | "" : String | GlobalDataFlow.cs:159:20:159:24 | access to local variable sink8 : String | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this | -| GlobalDataFlow.cs:159:9:159:25 | this access : DataFlow | GlobalDataFlow.cs:326:10:326:15 | this : DataFlow | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | -| GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 : String | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:161:13:161:31 | SSA def(sink12) : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | -| GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 : IEnumerable | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this | -| GlobalDataFlow.cs:161:22:161:31 | this access : DataFlow | GlobalDataFlow.cs:331:25:331:32 | this : DataFlow | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : String | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:163:13:163:43 | SSA def(sink23) : T | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | -| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : String | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : T | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:163:35:163:42 | access to local variable nonSink0 : T | GlobalDataFlow.cs:378:39:378:45 | tainted : T | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:167:9:167:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | GlobalDataFlow.cs:168:15:168:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this | -| GlobalDataFlow.cs:167:20:167:27 | this access : DataFlow | GlobalDataFlow.cs:338:12:338:17 | this : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this | -| GlobalDataFlow.cs:169:9:169:31 | this access : DataFlow | GlobalDataFlow.cs:343:10:343:18 | this : DataFlow | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 | -| GlobalDataFlow.cs:170:15:170:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:171:23:171:30 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this | -| GlobalDataFlow.cs:171:9:171:31 | this access : DataFlow | GlobalDataFlow.cs:348:10:348:18 | this : DataFlow | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | GlobalDataFlow.cs:172:15:172:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:20:173:40 | call to method First | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:173:20:173:40 | call to method First : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this | -| GlobalDataFlow.cs:173:20:173:32 | this access : DataFlow | GlobalDataFlow.cs:353:25:353:35 | this : DataFlow | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:173:9:173:40 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:173:20:173:40 | call to method First : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 | -| GlobalDataFlow.cs:174:15:174:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:175:9:175:44 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | GlobalDataFlow.cs:176:15:176:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:175:36:175:43 | access to local variable nonSink0 : String | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:179:22:179:48 | SSA def(out) : Func | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out | -| GlobalDataFlow.cs:179:29:179:48 | (...) => ... : Func | GlobalDataFlow.cs:180:21:180:24 | access to local variable out : Func | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call | -| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:180:13:180:26 | SSA def(sink9) : String | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | -| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 : String | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:184:22:184:38 | SSA def(nonOut) : Func | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut | -| GlobalDataFlow.cs:184:31:184:38 | (...) => ... : Func | GlobalDataFlow.cs:185:20:185:25 | access to local variable nonOut : Func | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call | -| GlobalDataFlow.cs:184:37:184:38 | "" : String | GlobalDataFlow.cs:185:20:185:27 | delegate call : String | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:185:9:185:27 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:185:20:185:27 | delegate call : String | GlobalDataFlow.cs:186:15:186:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : Lazy | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : Lazy | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:13:189:48 | SSA def(sink10) : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | -| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 : String | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:189:39:189:41 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : Lazy | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:43 | object creation of type Lazy : Lazy | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : Lazy | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:9:193:49 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:193:20:193:49 | access to property Value : String | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:194:15:194:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:193:37:193:42 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:197:13:197:32 | SSA def(sink19) : String | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 : String | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this | -| GlobalDataFlow.cs:197:22:197:32 | this access : DataFlow | GlobalDataFlow.cs:415:9:415:11 | this : DataFlow | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | GlobalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this | -| GlobalDataFlow.cs:201:20:201:33 | this access : DataFlow | GlobalDataFlow.cs:420:9:420:11 | this : DataFlow | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:205:39:205:45 | tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:205:39:205:45 | tainted : Object | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:205:67:205:76 | notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:205:67:205:76 | notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:205:67:205:76 | notTainted : Object | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : Object | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:208:30:208:92 | SSA def(f1) : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:208:35:208:92 | (...) => ... : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:208:79:208:89 | access to parameter sinkParam10 : String | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:71:209:71 | x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : Object | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:71 | x : String | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:209:66:209:90 | SSA def(f2) : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:209:71:209:90 | (...) => ... : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:13:210:39 | SSA def(sink24) : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:22:210:39 | call to method Select | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:210:22:210:39 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 : IEnumerable | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 | -| GlobalDataFlow.cs:210:37:210:38 | access to local variable f1 : Func | GlobalDataFlow.cs:220:41:220:42 | access to local variable f1 : Func | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:13:212:39 | SSA def(sink25) : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:22:212:39 | call to method Select | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:212:22:212:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 | -| GlobalDataFlow.cs:212:37:212:38 | access to local variable f2 : Expression> | GlobalDataFlow.cs:222:37:222:38 | access to local variable f2 : Expression> | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:13:214:49 | SSA def(sink26) : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:22:214:49 | call to method Select | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:214:22:214:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 : IEnumerable | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : Object | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:218:30:218:95 | SSA def(f3) : Func | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 | -| GlobalDataFlow.cs:218:35:218:95 | (...) => ... : Func | GlobalDataFlow.cs:224:37:224:38 | access to local variable f3 : Func | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:59:218:70 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:218:81:218:92 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:71:219:71 | x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : Object | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:71 | x : String | GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:219:66:219:92 | SSA def(f4) : Expression> | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 | -| GlobalDataFlow.cs:219:71:219:92 | (...) => ... : Expression> | GlobalDataFlow.cs:226:37:226:38 | access to local variable f4 : Expression> | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:219:91:219:91 | access to parameter x : String | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:220:23:220:32 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:13:220:43 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:23:220:43 | call to method Select | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:220:23:220:43 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink | -| GlobalDataFlow.cs:220:41:220:42 | [output] access to local variable f1 : String | GlobalDataFlow.cs:221:15:221:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:222:19:222:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:9:222:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:19:222:39 | call to method Select | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:222:19:222:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink | -| GlobalDataFlow.cs:222:37:222:38 | [output] access to local variable f2 : T | GlobalDataFlow.cs:223:15:223:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:218:35:218:46 | nonSinkParam : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:224:19:224:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:9:224:39 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:19:224:39 | call to method Select | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:224:19:224:39 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink | -| GlobalDataFlow.cs:224:37:224:38 | [output] access to local variable f3 : String | GlobalDataFlow.cs:225:15:225:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:219:71:219:71 | x : IQueryable | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted | -| GlobalDataFlow.cs:226:19:226:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : String | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:9:226:39 | SSA def(nonSink) : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:19:226:39 | call to method Select | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:226:19:226:39 | call to method Select : IQueryable | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink | -| GlobalDataFlow.cs:226:37:226:38 | [output] access to local variable f4 : T | GlobalDataFlow.cs:227:15:227:21 | access to local variable nonSink : IQueryable | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:228:19:228:28 | access to parameter notTainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:9:228:49 | SSA def(nonSink) : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:19:228:49 | call to method Select | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:228:19:228:49 | call to method Select : IEnumerable | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink | -| GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:229:15:229:21 | access to local variable nonSink : IEnumerable | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : Object | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : T | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : Object | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : T | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : Object | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : String | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : Object | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : String | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : T | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : Object | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : String | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : T | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : Object | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : String | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : T | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : Object | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : String | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : T | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : Object | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : String | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : String | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 | -| GlobalDataFlow.cs:270:29:270:41 | nonSinkParam0 : T | GlobalDataFlow.cs:272:15:272:27 | access to parameter nonSinkParam0 : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | -| GlobalDataFlow.cs:275:26:275:26 | x : Object | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : String | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:275:26:275:26 | x : T | GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:277:13:277:38 | SSA def(y) : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : Object | -| GlobalDataFlow.cs:277:27:277:28 | x0 : Object | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : String | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : String | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:28 | x0 : T | GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:277:27:277:34 | (...) => ... : Func | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:277:33:277:34 | access to parameter x0 : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : Object | GlobalDataFlow.cs:364:46:364:46 | x : Object | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : String | GlobalDataFlow.cs:364:46:364:46 | x : String | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:277:37:277:37 | access to parameter x : T | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | GlobalDataFlow.cs:278:16:278:24 | ... == ... : Boolean | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:16 | (...) ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : Object | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:16 | (...) ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : String | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:16 | (...) ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:16 | access to local variable y : T | GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:70:21:70:46 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:72:29:72:101 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:100:24:100:33 | call to method Return : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:102:28:102:103 | call to method Invoke : T | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:28:278:37 | default(...) : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : Object | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : Object | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : String | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : String | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:278:41:278:41 | access to local variable y : T | GlobalDataFlow.cs:278:16:278:41 | ... ? ... : ... : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:281:32:281:32 | x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:281:32:281:32 | x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | -| GlobalDataFlow.cs:281:32:281:32 | x : Object | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : String | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:281:32:281:32 | x : T | GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:75:30:75:34 | SSA def(sink2) : T | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | GlobalDataFlow.cs:104:27:104:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : Object | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : String | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : String | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:283:13:283:13 | access to parameter x : T | GlobalDataFlow.cs:283:9:283:13 | SSA def(y) : T | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) | -| GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | GlobalDataFlow.cs:106:41:106:48 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) | -| GlobalDataFlow.cs:284:13:284:22 | default(...) : T | GlobalDataFlow.cs:284:9:284:22 | SSA def(z) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:287:32:287:32 | x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:287:32:287:32 | x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | -| GlobalDataFlow.cs:287:32:287:32 | x : Object | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : String | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:32:287:32 | x : T | GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | -| GlobalDataFlow.cs:287:50:287:50 | z : Object | GlobalDataFlow.cs:287:50:287:50 | z | -| GlobalDataFlow.cs:287:50:287:50 | z : Object | GlobalDataFlow.cs:287:50:287:50 | z : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:108:27:108:34 | SSA def(nonSink0) : T | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) | -| GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | GlobalDataFlow.cs:110:30:110:34 | SSA def(sink1) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : Object | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : Object | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : String | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : String | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:289:13:289:13 | access to parameter x : T | GlobalDataFlow.cs:289:9:289:13 | SSA def(y) : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : IEnumerable | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : Object | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:295:16:295:25 | access to parameter sinkParam8 : T | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : Object | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : String | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 | -| GlobalDataFlow.cs:301:16:301:25 | access to parameter sinkParam9 : T | GlobalDataFlow.cs:209:76:209:90 | call to method ReturnCheck2 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : Object | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:307:16:307:26 | access to parameter sinkParam11 : T | GlobalDataFlow.cs:228:37:228:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : Object | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:310:34:310:45 | nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : String | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : String | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam | -| GlobalDataFlow.cs:312:15:312:26 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck | -| GlobalDataFlow.cs:313:16:313:27 | access to parameter nonSinkParam : T | GlobalDataFlow.cs:219:76:219:92 | call to method NonReturnCheck : T | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:333:22:333:23 | "" : String | GlobalDataFlow.cs:333:22:333:23 | "" | -| GlobalDataFlow.cs:333:22:333:23 | "" : String | GlobalDataFlow.cs:333:22:333:23 | "" : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield | -| GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:335:22:335:23 | "" : String | GlobalDataFlow.cs:335:22:335:23 | "" | -| GlobalDataFlow.cs:335:22:335:23 | "" : String | GlobalDataFlow.cs:335:22:335:23 | "" : IEnumerable | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:167:20:167:27 | call to method NonOut : String | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func | -| GlobalDataFlow.cs:340:16:340:17 | "" : String | GlobalDataFlow.cs:193:37:193:42 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | GlobalDataFlow.cs:169:23:169:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) | -| GlobalDataFlow.cs:345:13:345:14 | "" : String | GlobalDataFlow.cs:345:9:345:14 | SSA def(x) : String | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) | -| GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | GlobalDataFlow.cs:171:23:171:30 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) | -| GlobalDataFlow.cs:350:13:350:14 | "" : String | GlobalDataFlow.cs:350:9:350:14 | SSA def(x) : String | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:355:22:355:23 | "" : String | GlobalDataFlow.cs:355:22:355:23 | "" | -| GlobalDataFlow.cs:355:22:355:23 | "" : String | GlobalDataFlow.cs:355:22:355:23 | "" : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield | -| GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | GlobalDataFlow.cs:173:20:173:32 | call to method NonOutYield : IEnumerable | -| GlobalDataFlow.cs:356:22:356:23 | "" : String | GlobalDataFlow.cs:356:22:356:23 | "" | -| GlobalDataFlow.cs:356:22:356:23 | "" : String | GlobalDataFlow.cs:356:22:356:23 | "" : IEnumerable | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Action | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:359:36:359:36 | a | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:359:36:359:36 | a : Action | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:361:9:361:9 | access to parameter a | -| GlobalDataFlow.cs:359:36:359:36 | a : Object | GlobalDataFlow.cs:361:9:361:9 | access to parameter a : Action | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:359:41:359:41 | x | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:359:41:359:41 | x : T | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : Object | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x | -| GlobalDataFlow.cs:359:41:359:41 | x : T | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:53:15:53:15 | x : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:60:15:60:27 | nonSinkParam0 : T | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : T | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : T | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Func | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:364:41:364:41 | f | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:364:41:364:41 | f : Func | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:366:16:366:16 | access to parameter f | -| GlobalDataFlow.cs:364:41:364:41 | f : Object | GlobalDataFlow.cs:366:16:366:16 | access to parameter f : Func | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:364:46:364:46 | x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:364:46:364:46 | x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | -| GlobalDataFlow.cs:364:46:364:46 | x : Object | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : String | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:364:46:364:46 | x : T | GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : String | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : String | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:134:45:134:64 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:143:21:143:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:147:20:147:40 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:149:20:149:44 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:16:366:19 | delegate call : T | GlobalDataFlow.cs:277:17:277:38 | call to method ApplyFunc : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:275:26:275:26 | x : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:277:27:277:28 | x0 : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : Object | GlobalDataFlow.cs:366:16:366:19 | delegate call : Object | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:275:26:275:26 | x : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:277:27:277:28 | x0 : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : String | GlobalDataFlow.cs:366:16:366:19 | delegate call : String | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:275:26:275:26 | x : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:277:27:277:28 | x0 : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:366:18:366:18 | access to parameter x : T | GlobalDataFlow.cs:366:16:366:19 | delegate call : T | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:373:42:373:42 | a | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:373:42:373:42 | a : MyDelegate | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:375:9:375:9 | access to parameter a | -| GlobalDataFlow.cs:373:42:373:42 | a : Object | GlobalDataFlow.cs:375:9:375:9 | access to parameter a : MyDelegate | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:373:52:373:52 | x | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:373:52:373:52 | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : Object | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:61:38:61:50 | nonSinkParam0 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:378:39:378:45 | tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:378:39:378:45 | tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : Object | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:380:13:380:28 | SSA def(sink11) : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:380:22:380:28 | access to parameter tainted : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 : T | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : T | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:385:42:385:51 | nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : Object | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:385:42:385:51 | nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:387:13:387:33 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:387:24:387:33 | access to parameter nonTainted : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 : String | GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam | -| GlobalDataFlow.cs:389:16:389:23 | access to local variable nonSink0 : String | GlobalDataFlow.cs:175:20:175:44 | call to method NonTaintedParam : String | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 | -| GlobalDataFlow.cs:398:62:398:63 | "" : String | GlobalDataFlow.cs:32:15:32:35 | access to property NonSinkProperty1 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:9:404:11 | value | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:9:404:11 | value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : Object | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:19:404:32 | SSA def(sink20) : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:404:28:404:32 | access to parameter value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:9:410:11 | value | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:9:410:11 | value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : Object | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:9:410:11 | value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:19:410:34 | SSA def(nonSink0) : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:410:30:410:34 | access to parameter value : String | GlobalDataFlow.cs:410:43:410:50 | access to local variable nonSink0 : String | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty | -| GlobalDataFlow.cs:420:22:420:23 | "" : String | GlobalDataFlow.cs:201:20:201:33 | access to property NonOutProperty : String | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:426:71:426:71 | e | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:426:71:426:71 | e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : Object | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:71:426:71 | e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Func | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:426:85:426:85 | f | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:426:85:426:85 | f : Func | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:431:44:431:44 | access to parameter f | -| GlobalDataFlow.cs:426:85:426:85 | f : Object | GlobalDataFlow.cs:431:44:431:44 | access to parameter f : Func | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:428:13:428:17 | SSA def(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:428:17:428:17 | 0 : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : IEnumerable | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:429:22:429:22 | SSA def(x) : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:429:27:429:27 | access to parameter e : String[] | GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:429:9:432:9 | SSA phi(i) : Int32 | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i | -| GlobalDataFlow.cs:431:17:431:19 | SSA def(i) : Int32 | GlobalDataFlow.cs:431:17:431:17 | access to local variable i : Int32 | -| GlobalDataFlow.cs:431:17:431:23 | ... % ... : Int32 | GlobalDataFlow.cs:431:17:431:28 | ... == ... | -| GlobalDataFlow.cs:431:17:431:23 | ... % ... : Int32 | GlobalDataFlow.cs:431:17:431:28 | ... == ... : Boolean | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | GlobalDataFlow.cs:112:24:112:90 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : String | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:44:431:47 | delegate call : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : IEnumerable | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:80:79:80:79 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:112:84:112:84 | x : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| GlobalDataFlow.cs:431:46:431:46 | access to local variable x : T | GlobalDataFlow.cs:431:44:431:47 | delegate call : T | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:3:18:3:18 | b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:3:18:3:18 | b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:5:13:5:13 | access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:5:13:5:13 | access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:3:18:3:18 | b : Object | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:3:28:3:34 | tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:3:28:3:34 | tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : Object | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): false] access to parameter b : Boolean | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b | -| Splitting.cs:5:13:5:13 | access to parameter b : Boolean | Splitting.cs:10:13:10:13 | [b (line 3): true] access to parameter b : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:6:17:6:31 | [b (line 3): true] ... == ... : Boolean | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted | -| Splitting.cs:6:17:6:23 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): false] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:8:13:8:31 | [b (line 3): true] SSA def(x) : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : String | Splitting.cs:11:19:11:19 | access to local variable x : String | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x | -| Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x : T | Splitting.cs:11:19:11:19 | access to local variable x : T | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:26:16:26 | x : T | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : Object | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : String | Splitting.cs:16:32:16:32 | access to parameter x : String | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x | -| Splitting.cs:16:26:16:26 | x : T | Splitting.cs:16:32:16:32 | access to parameter x : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:20:22:20:30 | call to method Return : T | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:16:32:16:32 | access to parameter x : T | Splitting.cs:21:21:21:33 | call to method Return : T | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : Object | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:18:24:18:24 | s : String | Splitting.cs:20:29:20:29 | access to parameter s : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:20:22:20:30 | call to method Return : T | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:20:29:20:29 | access to parameter s : String | Splitting.cs:20:22:20:30 | call to method Return : String | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : Object | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:9:21:11 | value : String | Splitting.cs:21:28:21:32 | access to parameter value : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:16:26:16:26 | x : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:21:28:21:32 | access to parameter value : String | Splitting.cs:21:21:21:33 | call to method Return : String | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:10:24:11 | this : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:24:18:24:18 | b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:24:18:24:18 | b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:26:13:26:13 | access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:26:13:26:13 | access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:24:18:24:18 | b : Object | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:24:28:24:34 | tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:24:28:24:34 | tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:24:28:24:34 | tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): false] access to parameter b : Boolean | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b | -| Splitting.cs:26:13:26:13 | access to parameter b : Boolean | Splitting.cs:33:13:33:13 | [b (line 24): true] access to parameter b : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:27:17:27:31 | [b (line 24): true] ... == ... : Boolean | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:27:17:27:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): false] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): false] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:29:17:29:24 | [b (line 24): true] SSA def(d) : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:29:21:29:24 | [b (line 24): true] this access : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:21:9:21:11 | this : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:21:9:21:11 | this : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:21:9:21:11 | value : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:9 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:30:9:30:13 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:30:17:30:23 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): false] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:20:9:20:11 | this : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:20:9:20:11 | this : Splitting | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:17 | [b (line 24): true] access to local variable d : Splitting | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): false] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): false] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:31:13:31:26 | [b (line 24): true] SSA def(x) : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): false] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): false] dynamic access to element : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:18:24:18:24 | s : String | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element | -| Splitting.cs:31:19:31:25 | [b (line 24): true] access to parameter tainted : String | Splitting.cs:31:17:31:26 | [b (line 24): true] dynamic access to element : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : Object | Splitting.cs:34:19:34:19 | access to local variable x : Object | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : String | Splitting.cs:34:19:34:19 | access to local variable x : String | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x | -| Splitting.cs:32:15:32:15 | [b (line 24): true] access to local variable x : T | Splitting.cs:34:19:34:19 | access to local variable x : T | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:11:13:11:16 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:11:13:11:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:9:12:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:12:16:12:19 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:9:13:15 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:13:11:13:14 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:15:9:15:12 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:20:9:20 | this : This | This.cs:16:9:16:16 | this access : This | -| This.cs:9:27:9:31 | other : Object | This.cs:9:27:9:31 | other | -| This.cs:9:27:9:31 | other : Object | This.cs:9:27:9:31 | other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Object | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Object | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:14:13:14:17 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:14:13:14:17 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:9:27:9:31 | other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:9:12:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:9:12:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:11:13:11:16 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:12:16:12:19 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:12:16:12:19 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:9:12:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:9:13:15 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:9:13:15 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:12:16:12:19 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:13:11:13:14 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:13:11:13:14 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:9:13:15 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:15:9:15:12 | this access : Sub | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:15:9:15:12 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:13:11:13:14 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:15:16:15:20 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:15:16:15:20 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:14:13:14:17 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : Sub | This.cs:16:9:16:16 | this access : Sub | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:9:15:12 | this access : This | This.cs:16:9:16:16 | this access : This | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : Sub | This.cs:16:11:16:15 | access to parameter other : Sub | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:15:16:15:20 | access to parameter other : This | This.cs:16:11:16:15 | access to parameter other : This | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:9:16:16 | this access : This | This.cs:9:20:9:20 | this : This | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:16:11:16:15 | access to parameter other : This | This.cs:9:27:9:31 | other : This | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this | -| This.cs:17:9:17:18 | malloc : This | This.cs:7:5:7:8 | this : This | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:13:26:16 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access | -| This.cs:24:14:24:15 | this : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this | -| This.cs:26:13:26:16 | this access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:26:20:26:23 | this access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:13:26:16 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:26:20:26:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:13:27:16 | base access : Sub | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:26:20:26:23 | this access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : Sub | This.cs:9:20:9:20 | this : Sub | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : Sub | This.cs:27:20:27:23 | this access : Sub | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this | -| This.cs:27:13:27:16 | base access : This | This.cs:9:20:9:20 | this : This | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access | -| This.cs:27:13:27:16 | base access : This | This.cs:27:20:27:23 | this access : This | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : Sub | This.cs:9:27:9:31 | other : Sub | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other | -| This.cs:27:20:27:23 | this access : This | This.cs:9:27:9:31 | other : This | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this | -| This.cs:28:13:28:21 | malloc : Sub | This.cs:22:9:22:11 | this : Sub | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql deleted file mode 100644 index 163130bea8f..00000000000 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingEdges.ql +++ /dev/null @@ -1,17 +0,0 @@ -import csharp -import DataFlow -import semmle.code.csharp.dataflow.internal.DataFlowPrivate - -class ConfigAny extends TaintTracking::Configuration { - ConfigAny() { this = "ConfigAny" } - - override predicate isSource(Node source) { - source instanceof PostUpdateNode implies source.asExpr() instanceof ObjectCreation - } - - override predicate isSink(Node sink) { - sink instanceof PostUpdateNode implies sink.asExpr() instanceof ObjectCreation - } -} - -query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index c612897d3ee..7495630f875 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -75,7 +75,7 @@ edges | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | +| GlobalDataFlow.cs:35:13:35:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | @@ -84,7 +84,7 @@ edges | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | +| GlobalDataFlow.cs:37:35:37:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | GlobalDataFlow.cs:44:50:44:59 | access to parameter sinkParam2 | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:44:30:44:39 | sinkParam2 : String | | GlobalDataFlow.cs:45:13:45:30 | access to property SinkProperty0 : String | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | @@ -100,31 +100,31 @@ edges | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:52:20:52:37 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:53:15:53:15 | x : String | GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | -| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | +| GlobalDataFlow.cs:53:24:53:24 | access to parameter x : String | GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:359:41:359:41 | x : String | +| GlobalDataFlow.cs:53:28:53:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:361:41:361:41 | x : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:54:44:54:61 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:55:28:55:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:56:37:56:37 | x : String | GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | -| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | +| GlobalDataFlow.cs:56:46:56:46 | access to parameter x : String | GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | | GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:373:52:373:52 | x : String | +| GlobalDataFlow.cs:57:35:57:52 | access to property SinkProperty0 : String | GlobalDataFlow.cs:375:52:375:52 | x : String | | GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | -| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:404:9:404:11 | value : String | +| GlobalDataFlow.cs:64:22:64:39 | access to property SinkProperty0 : String | GlobalDataFlow.cs:406:9:406:11 | value : String | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:71:15:71:19 | access to local variable sink0 | | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | GlobalDataFlow.cs:72:94:72:98 | access to local variable sink0 : String | | GlobalDataFlow.cs:70:28:70:45 | access to property SinkProperty0 : String | GlobalDataFlow.cs:70:21:70:46 | call to method Return : String | @@ -140,27 +140,27 @@ edges | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | | GlobalDataFlow.cs:78:30:78:34 | SSA def(sink3) : String | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | -| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | +| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:88 | call to method First : String | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | +| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | +| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | +| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | +| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | +| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | GlobalDataFlow.cs:143:39:143:43 | access to local variable sink4 : String | | GlobalDataFlow.cs:135:29:135:33 | access to local variable sink3 : String | GlobalDataFlow.cs:135:21:135:34 | delegate call : String | @@ -175,56 +175,56 @@ edges | GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | +| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | +| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | +| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | +| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:56:37:56:37 | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted : String | | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | @@ -333,22 +333,22 @@ nodes | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable | semmle.label | call to method SelectEven : IEnumerable | | GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | semmle.label | (...) ... : String[] | | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | semmle.label | access to local variable sink13 | -| GlobalDataFlow.cs:82:23:82:74 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:82:84:82:94 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | semmle.label | access to local variable sink14 | -| GlobalDataFlow.cs:84:23:84:74 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:84:125:84:135 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | semmle.label | access to local variable sink15 | -| GlobalDataFlow.cs:86:70:86:121 | (...) ... : String[] | semmle.label | (...) ... : String[] | -| GlobalDataFlow.cs:86:125:86:135 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | semmle.label | access to local variable sink16 | -| GlobalDataFlow.cs:88:22:88:27 | access to local variable sink14 : IEnumerable | semmle.label | access to local variable sink14 : IEnumerable | -| GlobalDataFlow.cs:88:43:88:61 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | -| GlobalDataFlow.cs:88:64:88:69 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | semmle.label | (...) ... : String[] | +| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | semmle.label | access to local variable sink17 | -| GlobalDataFlow.cs:90:75:90:88 | call to method First : String | semmle.label | call to method First : String | -| GlobalDataFlow.cs:90:91:90:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | -| GlobalDataFlow.cs:90:112:90:117 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | semmle.label | access to local variable sink14 : String | +| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | +| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String | | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | semmle.label | access to local variable sink18 | | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | semmle.label | access to local variable sink21 | | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | semmle.label | access to local variable sink22 | @@ -375,64 +375,64 @@ nodes | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 | | GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String | | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 | -| GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | semmle.label | tainted : IQueryable | -| GlobalDataFlow.cs:208:35:208:45 | sinkParam10 : IQueryable | semmle.label | sinkParam10 : IQueryable | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 | -| GlobalDataFlow.cs:209:71:209:71 | x : IQueryable | semmle.label | x : IQueryable | -| GlobalDataFlow.cs:209:89:209:89 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:210:22:210:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:210:37:210:38 | [output] access to local variable f1 : String | semmle.label | [output] access to local variable f1 : String | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | semmle.label | access to local variable sink24 | -| GlobalDataFlow.cs:212:22:212:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f2 : String | semmle.label | [output] access to local variable f2 : String | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | semmle.label | access to local variable sink25 | -| GlobalDataFlow.cs:214:22:214:28 | access to parameter tainted : IQueryable | semmle.label | access to parameter tainted : IQueryable | -| GlobalDataFlow.cs:214:37:214:48 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | -| GlobalDataFlow.cs:234:26:234:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | -| GlobalDataFlow.cs:236:16:236:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | -| GlobalDataFlow.cs:240:26:240:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | -| GlobalDataFlow.cs:245:26:245:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | -| GlobalDataFlow.cs:250:26:250:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | -| GlobalDataFlow.cs:255:26:255:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | -| GlobalDataFlow.cs:260:26:260:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | -| GlobalDataFlow.cs:265:26:265:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | -| GlobalDataFlow.cs:292:31:292:40 | sinkParam8 : String[] | semmle.label | sinkParam8 : String[] | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | -| GlobalDataFlow.cs:298:32:298:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | -| GlobalDataFlow.cs:304:32:304:42 | sinkParam11 : IQueryable | semmle.label | sinkParam11 : IQueryable | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | -| GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:323:9:323:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:328:9:328:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | -| GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : IEnumerable | semmle.label | "taint source" : IEnumerable | -| GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | semmle.label | "taint source" : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:359:41:359:41 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:361:11:361:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:373:52:373:52 | x : String | semmle.label | x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:375:11:375:11 | access to parameter x : String | semmle.label | access to parameter x : String | -| GlobalDataFlow.cs:378:39:378:45 | tainted : String | semmle.label | tainted : String | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | -| GlobalDataFlow.cs:382:16:382:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | -| GlobalDataFlow.cs:404:9:404:11 | value : String | semmle.label | value : String | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | -| GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable | semmle.label | sinkParam10 : IQueryable | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 | +| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable | semmle.label | x : IQueryable | +| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | semmle.label | [output] access to local variable f1 : String | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | semmle.label | access to local variable sink24 | +| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | semmle.label | [output] access to local variable f2 : String | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | semmle.label | access to local variable sink25 | +| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable | semmle.label | access to local variable tainted : IQueryable | +| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func : T | semmle.label | [output] delegate creation of type Func : T | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | semmle.label | access to local variable sink26 | +| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | semmle.label | sinkParam0 : String | +| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | semmle.label | access to parameter sinkParam0 | +| GlobalDataFlow.cs:242:26:242:35 | sinkParam1 : String | semmle.label | sinkParam1 : String | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | semmle.label | access to parameter sinkParam1 | +| GlobalDataFlow.cs:247:26:247:35 | sinkParam3 : String | semmle.label | sinkParam3 : String | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | semmle.label | access to parameter sinkParam3 | +| GlobalDataFlow.cs:252:26:252:35 | sinkParam4 : String | semmle.label | sinkParam4 : String | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | semmle.label | access to parameter sinkParam4 | +| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | semmle.label | sinkParam5 : String | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | semmle.label | access to parameter sinkParam5 | +| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | semmle.label | sinkParam6 : String | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 | +| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | semmle.label | sinkParam7 : String | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 | +| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | semmle.label | sinkParam8 : String[] | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 | +| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | semmle.label | sinkParam9 : String | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 | +| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable | semmle.label | sinkParam11 : IQueryable | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 | +| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | semmle.label | SSA def(x) : String | +| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable | semmle.label | "taint source" : IEnumerable | +| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | semmle.label | "taint source" : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:375:52:375:52 | x : String | semmle.label | x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:377:11:377:11 | access to parameter x : String | semmle.label | access to parameter x : String | +| GlobalDataFlow.cs:380:39:380:45 | tainted : String | semmle.label | tainted : String | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | semmle.label | access to local variable sink11 | +| GlobalDataFlow.cs:384:16:384:21 | access to local variable sink11 : String | semmle.label | access to local variable sink11 : String | +| GlobalDataFlow.cs:406:9:406:11 | value : String | semmle.label | value : String | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | semmle.label | access to local variable sink20 | +| GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | semmle.label | "taint source" : String | | Splitting.cs:3:28:3:34 | tainted : String | semmle.label | tainted : String | | Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return : String | semmle.label | [b (line 3): false] call to method Return : String | | Splitting.cs:8:17:8:31 | [b (line 3): true] call to method Return : String | semmle.label | [b (line 3): true] call to method Return : String | @@ -485,30 +485,30 @@ nodes | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 | access to local variable sink22 | | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:136:15:136:19 | access to local variable sink4 | access to local variable sink4 | | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:144:15:144:19 | access to local variable sink5 | access to local variable sink5 | -| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | -| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:323:13:323:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | -| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:328:13:328:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | -| GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | GlobalDataFlow.cs:334:22:334:35 | "taint source" : String | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | access to local variable sink12 | -| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | +| GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:154:15:154:19 | access to local variable sink6 | access to local variable sink6 | +| GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:157:15:157:19 | access to local variable sink7 | access to local variable sink7 | +| GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:160:15:160:19 | access to local variable sink8 | access to local variable sink8 | +| GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:162:15:162:20 | access to local variable sink12 | access to local variable sink12 | +| GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 | access to local variable sink23 | | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | access to local variable sink9 | -| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:318:16:318:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | -| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:415:22:415:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | -| GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:208:58:208:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | -| GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:211:15:211:20 | access to local variable sink24 | access to local variable sink24 | -| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink25 | access to local variable sink25 | -| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink26 | access to local variable sink26 | -| GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:237:15:237:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | -| GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:242:15:242:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | -| GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:247:15:247:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | -| GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:252:15:252:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | -| GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:257:15:257:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | -| GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:262:15:262:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | -| GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:267:15:267:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | -| GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:294:15:294:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | -| GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:300:15:300:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | -| GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:205:39:205:45 | tainted : IQueryable | GlobalDataFlow.cs:306:15:306:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | -| GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | GlobalDataFlow.cs:378:39:378:45 | tainted : String | GlobalDataFlow.cs:381:15:381:20 | access to local variable sink11 | access to local variable sink11 | -| GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:404:41:404:46 | access to local variable sink20 | access to local variable sink20 | +| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | access to local variable sink10 | +| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | GlobalDataFlow.cs:417:22:417:35 | "taint source" : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | access to local variable sink19 | +| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | access to parameter sinkParam10 | +| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | access to local variable sink24 | +| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | access to local variable sink25 | +| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | access to local variable sink26 | +| GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 | access to parameter sinkParam0 | +| GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:244:15:244:24 | access to parameter sinkParam1 | access to parameter sinkParam1 | +| GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:249:15:249:24 | access to parameter sinkParam3 | access to parameter sinkParam3 | +| GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:254:15:254:24 | access to parameter sinkParam4 | access to parameter sinkParam4 | +| GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 | access to parameter sinkParam5 | +| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | access to parameter sinkParam6 | +| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | access to parameter sinkParam7 | +| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | access to parameter sinkParam8 | +| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | access to parameter sinkParam9 | +| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | access to parameter sinkParam11 | +| GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | GlobalDataFlow.cs:380:39:380:45 | tainted : String | GlobalDataFlow.cs:383:15:383:20 | access to local variable sink11 | access to local variable sink11 | +| GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | GlobalDataFlow.cs:17:27:17:40 | "taint source" : String | GlobalDataFlow.cs:406:41:406:46 | access to local variable sink20 | access to local variable sink20 | | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x | [b (line 3): false] access to local variable x | | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:9:15:9:15 | [b (line 3): true] access to local variable x | [b (line 3): true] access to local variable x | | Splitting.cs:11:19:11:19 | access to local variable x | Splitting.cs:3:28:3:34 | tainted : String | Splitting.cs:11:19:11:19 | access to local variable x | access to local variable x | diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index 6631539ed2d..ce4eba806a2 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -1139,6 +1139,8 @@ | System.Linq.Queryable.Aggregate(IQueryable, Expression>) | output from argument 1 -> return | false | | System.Linq.Queryable.All(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Any(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.AsQueryable(IEnumerable) | argument 0 -> return | false | +| System.Linq.Queryable.AsQueryable(IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected index 78c0204ed20..e9a03e58b0a 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlow.expected @@ -1,16 +1,12 @@ | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | | SSA.cs:9:15:9:22 | access to local variable ssaSink0 | | SSA.cs:25:15:25:22 | access to local variable ssaSink1 | | SSA.cs:43:15:43:22 | access to local variable ssaSink2 | diff --git a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected index 658dc392eee..e3166a0df30 100644 --- a/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/DataFlowStep.expected @@ -24,8 +24,7 @@ | Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) | | Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) | | Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i | -| LocalDataFlow.cs:49:23:49:23 | this | LocalDataFlow.cs:299:39:299:51 | this access | -| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b | +| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:85:21:85:21 | access to parameter b | | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | | LocalDataFlow.cs:53:15:53:19 | [post] access to local variable sink0 | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | @@ -38,567 +37,396 @@ | LocalDataFlow.cs:60:21:60:25 | "abc" | LocalDataFlow.cs:60:13:60:25 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | ... + ... | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | -| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | -| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | -| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | +| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | +| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | +| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | | LocalDataFlow.cs:65:9:65:25 | ... + ... | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:69:21:69:51 | object creation of type Dictionary | LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | -| LocalDataFlow.cs:70:9:70:13 | [post] access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | -| LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:74:24:74:55 | object creation of type Dictionary | LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | -| LocalDataFlow.cs:75:9:75:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | [post] access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:76:9:76:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:18:76:22 | [post] access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | -| LocalDataFlow.cs:80:21:80:32 | ... + ... | LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | -| LocalDataFlow.cs:81:15:81:19 | [post] access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:84:20:84:36 | ... + ... | LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:85:15:85:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | -| LocalDataFlow.cs:89:15:89:19 | [post] access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | LocalDataFlow.cs:93:15:93:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): false] access to parameter b | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): true] access to parameter b | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | -| LocalDataFlow.cs:96:25:96:27 | [b (line 49): true] "a" | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:24:100:28 | "abc" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | -| LocalDataFlow.cs:100:32:100:36 | "def" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | -| LocalDataFlow.cs:101:15:101:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:104:21:104:33 | (...) ... | LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | -| LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | LocalDataFlow.cs:104:21:104:33 | (...) ... | -| LocalDataFlow.cs:105:15:105:19 | [post] access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | LocalDataFlow.cs:109:15:109:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:108:24:108:39 | (...) ... | LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:108:24:108:39 | (...) ... | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:35 | ... as ... | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | -| LocalDataFlow.cs:112:21:112:35 | ... as ... | LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | -| LocalDataFlow.cs:113:15:113:19 | [post] access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | LocalDataFlow.cs:117:15:117:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:37 | ... as ... | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:116:20:116:37 | ... as ... | LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | -| LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | [post] access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | -| LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | -| LocalDataFlow.cs:124:39:124:40 | 42 | LocalDataFlow.cs:124:39:124:40 | (...) ... | -| LocalDataFlow.cs:125:15:125:22 | [post] access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | -| LocalDataFlow.cs:128:61:128:65 | [post] access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:129:15:129:20 | [post] access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | -| LocalDataFlow.cs:132:55:132:59 | [post] access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:133:15:133:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:136:22:136:27 | [post] access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:55 | call to method First | LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x | -| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value | -| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 | -| LocalDataFlow.cs:140:20:140:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:55 | (...) ... | LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | -| LocalDataFlow.cs:140:20:140:55 | call to method First | LocalDataFlow.cs:140:20:140:55 | (...) ... | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x | -| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value | -| LocalDataFlow.cs:141:15:141:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | -| LocalDataFlow.cs:144:34:144:38 | [post] access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | -| LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:147:22:147:56 | call to method TryParse | LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | -| LocalDataFlow.cs:147:37:147:41 | [post] access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:149:22:149:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:49 | call to method Replace | LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | -| LocalDataFlow.cs:149:44:149:48 | [post] access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:151:22:151:51 | call to method Format | LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | -| LocalDataFlow.cs:151:36:151:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:46:151:50 | [post] access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:152:15:152:20 | [post] access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:153:22:153:52 | call to method Format | LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | -| LocalDataFlow.cs:153:44:153:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:155:22:155:38 | call to method Parse | LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | -| LocalDataFlow.cs:155:33:155:37 | [post] access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:158:22:158:56 | call to method TryParse | LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | -| LocalDataFlow.cs:158:36:158:40 | [post] access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | -| LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:160:22:160:43 | call to method ToByte | LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | -| LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:162:22:162:46 | call to method Concat | LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | -| LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | (...) ... | -| LocalDataFlow.cs:163:15:163:20 | [post] access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:164:22:164:40 | call to method Copy | LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | -| LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | LocalDataFlow.cs:164:22:164:40 | call to method Copy | -| LocalDataFlow.cs:165:15:165:20 | [post] access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:166:22:166:54 | call to method Join | LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | -| LocalDataFlow.cs:167:15:167:20 | [post] access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:168:22:168:41 | call to method Insert | LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | -| LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | LocalDataFlow.cs:173:15:173:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:172:20:172:40 | call to method Parse | LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | -| LocalDataFlow.cs:172:32:172:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | LocalDataFlow.cs:175:15:175:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:174:24:174:61 | call to method TryParse | LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | -| LocalDataFlow.cs:174:39:174:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:50 | call to method Replace | LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | -| LocalDataFlow.cs:177:15:177:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:20:178:52 | call to method Format | LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | -| LocalDataFlow.cs:178:34:178:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | LocalDataFlow.cs:181:15:181:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:180:20:180:39 | call to method Parse | LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | -| LocalDataFlow.cs:180:31:180:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:182:20:182:57 | call to method TryParse | LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | -| LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | -| LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | LocalDataFlow.cs:185:15:185:23 | access to local variable nonSink14 | -| LocalDataFlow.cs:184:25:184:48 | call to method ToByte | LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | -| LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:186:20:186:46 | call to method Concat | LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | -| LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | (...) ... | -| LocalDataFlow.cs:187:15:187:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:20:188:40 | call to method Copy | LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | LocalDataFlow.cs:188:20:188:40 | call to method Copy | -| LocalDataFlow.cs:189:15:189:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:20:190:54 | call to method Join | LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | -| LocalDataFlow.cs:191:15:191:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | LocalDataFlow.cs:193:15:193:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:20:192:41 | call to method Insert | LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:196:22:196:32 | ... > ... | LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | -| LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:198:22:198:40 | call to method Equals | LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | -| LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:200:22:200:26 | [post] access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:45 | call to method Equals | LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | -| LocalDataFlow.cs:200:43:200:44 | 41 | LocalDataFlow.cs:200:35:200:44 | (...) ... | -| LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | LocalDataFlow.cs:205:15:205:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:204:20:204:24 | [post] access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:38 | call to method Equals | LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | -| LocalDataFlow.cs:204:33:204:37 | [post] access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:206:20:206:41 | call to method Equals | LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | -| LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | -| LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:210:22:210:31 | access to indexer | LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | -| LocalDataFlow.cs:211:15:211:20 | [post] access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:214:20:214:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:31 | access to indexer | LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | -| LocalDataFlow.cs:215:15:215:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | -| LocalDataFlow.cs:218:22:218:30 | access to array element | LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | -| LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | LocalDataFlow.cs:223:15:223:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | -| LocalDataFlow.cs:222:20:222:30 | access to array element | LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | -| LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | -| LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | LocalDataFlow.cs:231:15:231:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | -| LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | -| LocalDataFlow.cs:235:15:235:20 | [post] access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:236:22:236:27 | [post] access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:38 | call to method ToString | LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | -| LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:238:22:238:27 | [post] access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | -| LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:240:22:240:27 | [post] access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:33 | access to property Query | LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | -| LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | -| LocalDataFlow.cs:243:15:243:20 | [post] access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | -| LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | -| LocalDataFlow.cs:247:15:247:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | LocalDataFlow.cs:249:15:249:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:248:20:248:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:38 | call to method ToString | LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | LocalDataFlow.cs:251:15:251:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:250:20:250:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | LocalDataFlow.cs:253:15:253:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:252:20:252:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:33 | access to property Query | LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | -| LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | -| LocalDataFlow.cs:255:15:255:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | -| LocalDataFlow.cs:259:15:259:20 | [post] access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | -| LocalDataFlow.cs:261:15:261:20 | [post] access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | -| LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | -| LocalDataFlow.cs:265:15:265:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:267:15:267:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:270:22:270:127 | (...) ... | LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | -| LocalDataFlow.cs:270:30:270:119 | call to method Insert | LocalDataFlow.cs:270:30:270:127 | call to method Clone | -| LocalDataFlow.cs:270:30:270:127 | call to method Clone | LocalDataFlow.cs:270:22:270:127 | (...) ... | -| LocalDataFlow.cs:271:15:271:20 | [post] access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:272:22:272:27 | [post] access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:63 | call to method Split | LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | -| LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:276:20:276:127 | (...) ... | LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | -| LocalDataFlow.cs:276:28:276:119 | call to method Insert | LocalDataFlow.cs:276:28:276:127 | call to method Clone | -| LocalDataFlow.cs:276:28:276:127 | call to method Clone | LocalDataFlow.cs:276:20:276:127 | (...) ... | -| LocalDataFlow.cs:277:15:277:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | LocalDataFlow.cs:279:15:279:23 | access to local variable nonSink15 | -| LocalDataFlow.cs:278:25:278:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:68 | call to method Split | LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | -| LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | -| LocalDataFlow.cs:283:15:283:20 | [post] access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:284:22:284:38 | call to method ToString | LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | -| LocalDataFlow.cs:285:15:285:20 | [post] access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | -| LocalDataFlow.cs:287:9:287:14 | [post] access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | -| LocalDataFlow.cs:292:15:292:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:293:20:293:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:39 | call to method ToString | LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:294:15:294:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:295:9:295:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | -| LocalDataFlow.cs:299:39:299:51 | [output] delegate creation of type Func | LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | -| LocalDataFlow.cs:299:39:299:51 | this access | LocalDataFlow.cs:309:42:309:57 | this access | -| LocalDataFlow.cs:300:15:300:20 | [post] access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:33 | access to property Value | -| LocalDataFlow.cs:301:22:301:33 | access to property Value | LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | -| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | -| LocalDataFlow.cs:303:39:303:58 | [output] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | -| LocalDataFlow.cs:304:15:304:20 | [post] access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value | -| LocalDataFlow.cs:305:22:305:33 | access to property Value | LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | -| LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | -| LocalDataFlow.cs:309:42:309:57 | [output] delegate creation of type Func | LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | -| LocalDataFlow.cs:310:15:310:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | LocalDataFlow.cs:312:15:312:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:34 | access to property Value | -| LocalDataFlow.cs:311:20:311:34 | access to property Value | LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | -| LocalDataFlow.cs:313:38:313:45 | [output] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | -| LocalDataFlow.cs:314:15:314:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value | -| LocalDataFlow.cs:315:20:315:34 | access to property Value | LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:316:15:316:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:319:21:319:49 | object creation of type Dictionary | LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | -| LocalDataFlow.cs:320:9:320:13 | [post] access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | [post] access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:321:15:321:19 | [post] access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:322:22:322:26 | [post] access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:33 | access to property Values | LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | -| LocalDataFlow.cs:323:15:323:20 | [post] access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:324:22:324:37 | call to method Reverse | LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | -| LocalDataFlow.cs:328:9:328:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:22:329:26 | [post] access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:330:15:330:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | -| LocalDataFlow.cs:331:24:331:31 | [post] access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:38 | access to property Values | LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | -| LocalDataFlow.cs:332:15:332:22 | [post] access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | LocalDataFlow.cs:334:15:334:22 | access to local variable nonSink6 | -| LocalDataFlow.cs:333:24:333:41 | call to method Reverse | LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | -| LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:337:13:337:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:337:35:337:52 | object creation of type DataContract | LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | -| LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:338:22:338:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:48 | access to property AString | LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | -| LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:340:22:340:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:46 | [post] access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:57 | access to property AString | LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | -| LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | -| LocalDataFlow.cs:344:38:344:55 | object creation of type DataContract | LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | -| LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | LocalDataFlow.cs:346:15:346:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:345:20:345:49 | access to property AString | LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | -| LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | LocalDataFlow.cs:348:15:348:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:347:20:347:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:44 | access to property AnInt | LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | -| LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | LocalDataFlow.cs:350:15:350:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:349:20:349:53 | access to property AnInt | LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | -| LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | -| LocalDataFlow.cs:353:34:353:37 | null | LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | -| LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:354:22:354:40 | access to property Text | LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | -| LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | -| LocalDataFlow.cs:358:37:358:40 | null | LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | -| LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | LocalDataFlow.cs:360:15:360:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:359:20:359:41 | access to property Text | LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | -| LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | -| LocalDataFlow.cs:366:15:366:20 | [post] access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:35 | access to property Current | -| LocalDataFlow.cs:367:22:367:35 | access to property Current | LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | -| LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:369:57:369:77 | (...) ... | LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | -| LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | LocalDataFlow.cs:369:57:369:77 | (...) ... | -| LocalDataFlow.cs:370:15:370:20 | [post] access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:35 | access to property Current | -| LocalDataFlow.cs:371:22:371:35 | access to property Current | LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | -| LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:33 | access to property Value | -| LocalDataFlow.cs:373:22:373:33 | access to property Value | LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | -| LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | LocalDataFlow.cs:378:19:378:27 | access to local variable nonSink17 | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | -| LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | -| LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | -| LocalDataFlow.cs:380:15:380:23 | [post] access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | LocalDataFlow.cs:382:15:382:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:36 | access to property Current | -| LocalDataFlow.cs:381:20:381:36 | access to property Current | LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | -| LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | -| LocalDataFlow.cs:383:63:383:86 | (...) ... | LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | -| LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | LocalDataFlow.cs:383:63:383:86 | (...) ... | -| LocalDataFlow.cs:384:15:384:23 | [post] access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | -| LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:41 | access to property Current | -| LocalDataFlow.cs:385:25:385:41 | access to property Current | LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | -| LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | -| LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | LocalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:34 | access to property Value | -| LocalDataFlow.cs:387:20:387:34 | access to property Value | LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | -| LocalDataFlow.cs:391:31:391:50 | [output] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run | -| LocalDataFlow.cs:392:15:392:20 | [post] access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | -| LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | LocalDataFlow.cs:393:22:393:33 | await ... | -| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | -| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | -| LocalDataFlow.cs:397:34:397:41 | [output] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run | -| LocalDataFlow.cs:398:15:398:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | LocalDataFlow.cs:399:20:399:34 | await ... | -| LocalDataFlow.cs:400:15:400:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:403:22:403:36 | $"..." | LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | -| LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:407:20:407:37 | $"..." | LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | -| LocalDataFlow.cs:408:15:408:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:411:22:411:34 | ... = ... | LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | ... = ... | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | -| LocalDataFlow.cs:412:15:412:20 | [post] access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:415:20:415:38 | ... = ... | LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | LocalDataFlow.cs:415:20:415:38 | ... = ... | -| LocalDataFlow.cs:416:15:416:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | -| LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | -| LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | LocalDataFlow.cs:424:19:424:27 | access to local variable nonSink16 | -| LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | -| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 | -| LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:443:22:443:38 | ... ?? ... | LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:444:22:444:38 | ... ?? ... | LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | -| LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:464:28:464:30 | this | LocalDataFlow.cs:464:41:464:45 | this access | -| LocalDataFlow.cs:464:50:464:52 | this | LocalDataFlow.cs:464:56:464:60 | this access | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:64:464:68 | access to parameter value | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:477:15:477:24 | access to parameter nonTainted | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:483:21:483:21 | access to parameter x | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:486:32:486:33 | access to parameter os | -| LocalDataFlow.cs:483:21:483:21 | access to parameter x | LocalDataFlow.cs:483:16:483:21 | ... = ... | -| LocalDataFlow.cs:486:32:486:33 | access to parameter os | LocalDataFlow.cs:486:26:486:33 | ... = ... | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:493:29:493:32 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | [post] access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | +| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | +| LocalDataFlow.cs:69:21:69:32 | ... + ... | LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | +| LocalDataFlow.cs:70:15:70:19 | [post] access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:73:20:73:36 | ... + ... | LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:74:15:74:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | +| LocalDataFlow.cs:78:15:78:19 | [post] access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | LocalDataFlow.cs:82:15:82:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): false] access to parameter b | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): true] access to parameter b | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | +| LocalDataFlow.cs:85:25:85:27 | [b (line 49): true] "a" | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:24:89:28 | "abc" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | +| LocalDataFlow.cs:89:32:89:36 | "def" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | +| LocalDataFlow.cs:90:15:90:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:93:21:93:33 | (...) ... | LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | +| LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | LocalDataFlow.cs:93:21:93:33 | (...) ... | +| LocalDataFlow.cs:94:15:94:19 | [post] access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | LocalDataFlow.cs:98:15:98:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:97:24:97:39 | (...) ... | LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:97:24:97:39 | (...) ... | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:35 | ... as ... | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | +| LocalDataFlow.cs:101:21:101:35 | ... as ... | LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | +| LocalDataFlow.cs:102:15:102:19 | [post] access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:37 | ... as ... | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:105:20:105:37 | ... as ... | LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | +| LocalDataFlow.cs:106:15:106:22 | [post] access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:109:22:109:39 | call to method Parse | LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | +| LocalDataFlow.cs:109:34:109:38 | [post] access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | +| LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:112:22:112:56 | call to method TryParse | LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | +| LocalDataFlow.cs:112:37:112:41 | [post] access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:114:22:114:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:49 | call to method Replace | LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | +| LocalDataFlow.cs:114:44:114:48 | [post] access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:116:22:116:51 | call to method Format | LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | +| LocalDataFlow.cs:116:36:116:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:46:116:50 | [post] access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:117:15:117:20 | [post] access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:118:22:118:52 | call to method Format | LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | +| LocalDataFlow.cs:118:44:118:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:120:22:120:38 | call to method Parse | LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | +| LocalDataFlow.cs:120:33:120:37 | [post] access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:123:22:123:56 | call to method TryParse | LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | +| LocalDataFlow.cs:123:36:123:40 | [post] access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | +| LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:125:22:125:43 | call to method ToByte | LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | +| LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:127:22:127:46 | call to method Concat | LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | +| LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | (...) ... | +| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | +| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy | +| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:131:22:131:54 | call to method Join | LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | +| LocalDataFlow.cs:132:15:132:20 | [post] access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:133:22:133:41 | call to method Insert | LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | +| LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | LocalDataFlow.cs:138:15:138:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:137:20:137:40 | call to method Parse | LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | +| LocalDataFlow.cs:137:32:137:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | LocalDataFlow.cs:140:15:140:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:139:24:139:61 | call to method TryParse | LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | +| LocalDataFlow.cs:139:39:139:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:50 | call to method Replace | LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | +| LocalDataFlow.cs:142:15:142:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:20:143:52 | call to method Format | LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | +| LocalDataFlow.cs:143:34:143:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | LocalDataFlow.cs:146:15:146:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:145:20:145:39 | call to method Parse | LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | +| LocalDataFlow.cs:145:31:145:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:147:20:147:57 | call to method TryParse | LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | +| LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | +| LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | LocalDataFlow.cs:150:15:150:23 | access to local variable nonSink14 | +| LocalDataFlow.cs:149:25:149:48 | call to method ToByte | LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | +| LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:151:20:151:46 | call to method Concat | LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | +| LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | (...) ... | +| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy | +| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:20:155:54 | call to method Join | LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | +| LocalDataFlow.cs:156:15:156:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:20:157:41 | call to method Insert | LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:158:15:158:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:161:22:161:32 | ... > ... | LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | +| LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:163:22:163:26 | [post] access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:40 | call to method Equals | LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | +| LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:165:22:165:26 | [post] access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:45 | call to method Equals | LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | +| LocalDataFlow.cs:165:43:165:44 | 41 | LocalDataFlow.cs:165:35:165:44 | (...) ... | +| LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | LocalDataFlow.cs:170:15:170:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:169:20:169:24 | [post] access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:38 | call to method Equals | LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | +| LocalDataFlow.cs:169:33:169:37 | [post] access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:171:20:171:41 | call to method Equals | LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | +| LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | +| LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | +| LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | LocalDataFlow.cs:180:15:180:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | +| LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | +| LocalDataFlow.cs:184:15:184:20 | [post] access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:185:22:185:27 | [post] access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:38 | call to method ToString | LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | +| LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:187:22:187:27 | [post] access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | +| LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:189:22:189:27 | [post] access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:33 | access to property Query | LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | +| LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | +| LocalDataFlow.cs:192:15:192:20 | [post] access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | +| LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | +| LocalDataFlow.cs:196:15:196:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | LocalDataFlow.cs:198:15:198:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:197:20:197:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:38 | call to method ToString | LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | LocalDataFlow.cs:200:15:200:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:199:20:199:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | LocalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:201:20:201:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:33 | access to property Query | LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | +| LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | +| LocalDataFlow.cs:204:15:204:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | +| LocalDataFlow.cs:208:15:208:20 | [post] access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | +| LocalDataFlow.cs:210:15:210:20 | [post] access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | +| LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | +| LocalDataFlow.cs:214:15:214:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:216:15:216:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | +| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone | +| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... | +| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:221:22:221:27 | [post] access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | +| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | +| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone | +| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... | +| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | LocalDataFlow.cs:228:15:228:23 | access to local variable nonSink15 | +| LocalDataFlow.cs:227:25:227:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:68 | call to method Split | LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | +| LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | +| LocalDataFlow.cs:232:15:232:20 | [post] access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:233:22:233:38 | call to method ToString | LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | +| LocalDataFlow.cs:234:15:234:20 | [post] access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | +| LocalDataFlow.cs:236:9:236:14 | [post] access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | +| LocalDataFlow.cs:241:15:241:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:242:20:242:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:39 | call to method ToString | LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:243:15:243:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:244:9:244:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:248:13:248:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:248:35:248:52 | object creation of type DataContract | LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | +| LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:249:22:249:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:48 | access to property AString | LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | +| LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:251:22:251:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:46 | [post] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:57 | access to property AString | LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | +| LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:255:38:255:55 | object creation of type DataContract | LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | +| LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | LocalDataFlow.cs:257:15:257:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:256:20:256:49 | access to property AString | LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | +| LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | LocalDataFlow.cs:259:15:259:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:258:20:258:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:44 | access to property AnInt | LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | +| LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | LocalDataFlow.cs:261:15:261:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:260:20:260:53 | access to property AnInt | LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | +| LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:264:34:264:37 | null | LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | +| LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:265:22:265:40 | access to property Text | LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | +| LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:269:37:269:40 | null | LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | +| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | +| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run | +| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | +| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... | +| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | +| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | +| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run | +| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:282:20:282:34 | await ... | LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | +| LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | LocalDataFlow.cs:282:20:282:34 | await ... | +| LocalDataFlow.cs:283:15:283:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:286:22:286:36 | $"..." | LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | +| LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:290:20:290:37 | $"..." | LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | +| LocalDataFlow.cs:291:15:291:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:294:22:294:34 | ... = ... | LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | ... = ... | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | +| LocalDataFlow.cs:295:15:295:20 | [post] access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:298:20:298:38 | ... = ... | LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | LocalDataFlow.cs:298:20:298:38 | ... = ... | +| LocalDataFlow.cs:299:15:299:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | +| LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | +| LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | LocalDataFlow.cs:307:19:307:27 | access to local variable nonSink16 | +| LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | +| LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | LocalDataFlow.cs:321:23:321:31 | access to local variable nonSink17 | +| LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:326:22:326:38 | ... ?? ... | LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:327:22:327:38 | ... ?? ... | LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | +| LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:347:28:347:30 | this | LocalDataFlow.cs:347:41:347:45 | this access | +| LocalDataFlow.cs:347:50:347:52 | this | LocalDataFlow.cs:347:56:347:60 | this access | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:64:347:68 | access to parameter value | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:360:15:360:24 | access to parameter nonTainted | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:366:21:366:21 | access to parameter x | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:369:32:369:33 | access to parameter os | +| LocalDataFlow.cs:366:21:366:21 | access to parameter x | LocalDataFlow.cs:366:16:366:21 | ... = ... | +| LocalDataFlow.cs:369:32:369:33 | access to parameter os | LocalDataFlow.cs:369:26:369:33 | ... = ... | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:376:29:376:32 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | [post] access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:8:24:8:30 | access to parameter tainted | diff --git a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs index 6603abc50f1..eea36528104 100644 --- a/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs +++ b/csharp/ql/test/library-tests/dataflow/local/LocalDataFlow.cs @@ -65,17 +65,6 @@ public class LocalDataFlow nonSink0 += "abc"; Check(nonSink0); - // Assignment (indexer), tainted - var sink2 = new Dictionary(); - sink2[0][1] = sink1; - Check(sink2); - - // Assignment (indexer), not tainted - var nonSink1 = new Dictionary(); - nonSink1[""] = nonSink0; - nonSink1[sink1] = ""; // do not track tainted keys - Check(nonSink1); - // Concatenation, tainted var sink5 = sink1 + "ok"; Check(sink5); @@ -116,30 +105,6 @@ public class LocalDataFlow nonSink3 = nonSink0 as object; Check(nonSink3); - // Array creation (initializer), tainted - var sink10 = new object[] { sink9 }; - Check(sink10); - - // Array creation (initializer), not tainted - var nonSink4 = new object[] { 42 }; - Check(nonSink4); - - // Object creation (collection initializer), tainted - var sink11 = new Dictionary { { "", sink9 } }; - Check(sink11); - - // Object creation (collection initializer), not tainted - nonSink1 = new Dictionary { { sink9, "" } }; - Check(nonSink1); - - // Data-preserving LINQ, tainted - var sink14 = sink11.First(x => x.Value != null); - Check(sink14); - - // Data-preserving LINQ, not tainted - nonSink3 = nonSink1.First(x => x.Value != null); - Check(nonSink1); - // Standard method with a tainted argument, tainted var sink15 = Int32.Parse(sink9); Check(sink15); @@ -206,22 +171,6 @@ public class LocalDataFlow nonSink7 = sink8.Equals(nonSink3); Check(nonSink7); - // Indexer access, tainted - var sink23 = sink11[""]; - Check(sink23); - - // Indexer access, not tainted - nonSink0 = nonSink1[""]; - Check(nonSink0); - - // Array access, tainted - var sink24 = sink10[0]; - Check(sink24); - - // Array access, not tainted - nonSink3 = nonSink4[0]; - Check(nonSink3); - // Logical operation using tainted operand, tainted var sink25 = sink20 || false; Check(sink25); @@ -231,7 +180,7 @@ public class LocalDataFlow Check(nonSink7); // Ad hoc tracking (System.Uri), tainted - var sink26 = new System.Uri(sink23); + var sink26 = new System.Uri(sink9); Check(sink26); var sink27 = sink26.ToString(); Check(sink27); @@ -295,44 +244,6 @@ public class LocalDataFlow nonSink10.AppendLine(nonSink0); Check(nonSink10); - // Ad hoc tracking (System.Lazy), tainted - var sink40 = new Lazy(TaintedMethod); - Check(sink40); - var sink41 = sink40.Value; - Check(sink41); - var sink42 = new Lazy(() => "taint source"); - Check(sink42); - var sink43 = sink42.Value; - Check(sink43); - - // Ad hoc tracking (System.Lazy), not tainted - var nonSink12 = new Lazy(NonTaintedMethod); - Check(nonSink12); - nonSink0 = nonSink12.Value; - Check(nonSink0); - nonSink12 = new Lazy(() => ""); - Check(nonSink12); - nonSink0 = nonSink12.Value; - Check(nonSink0); - - // Ad hoc tracking (collections), tainted - var sink3 = new Dictionary(); - sink3.Add(0, sink1); - Check(sink3); - var sink12 = sink3.Values; - Check(sink12); - var sink13 = sink12.Reverse(); - Check(sink13); - - // Ad hoc tracking (collections), not tainted - nonSink1.Add("", nonSink0); - nonSink1.Add(sink1, ""); // do not track tainted keys - Check(nonSink1); - var nonSink5 = nonSink1.Values; - Check(nonSink5); - var nonSink6 = nonSink5.Reverse(); - Check(nonSink6); - // Ad hoc tracking (data contracts), tainted var taintedDataContract = new DataContract(); var sink53 = taintedDataContract.AString; @@ -359,34 +270,6 @@ public class LocalDataFlow nonSink0 = nonTaintedTextBox.Text; Check(nonSink0); - // Iteration over a tracked expression, tainted - foreach (var sink61 in sink10) - Check(sink61); - IEnumerator sink62 = sink10.GetEnumerator(); - Check(sink62); - var sink63 = sink62.Current; - Check(sink63); - IEnumerator> sink64 = sink3.GetEnumerator(); - Check(sink64); - var sink65 = sink64.Current; - Check(sink65); - var sink66 = sink65.Value; - Check(sink66); - - // Iteration over a tracked expression, not tainted - foreach (var nonSink17 in nonSink4) - Check(nonSink17); - IEnumerator nonSink18 = nonSink4.GetEnumerator(); - Check(nonSink18); - nonSink3 = nonSink18.Current; - Check(nonSink3); - IEnumerator> nonSink19 = nonSink1.GetEnumerator(); - Check(nonSink19); - var nonSink20 = nonSink19.Current; - Check(nonSink20); - nonSink0 = nonSink20.Value; - Check(nonSink0); - // async await, tainted var sink67 = Task.Run(() => "taint source"); Check(sink67); diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected index 756d79333c1..e8a0153dc92 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTracking.expected @@ -1,70 +1,51 @@ | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | -| LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | | SSA.cs:9:15:9:22 | access to local variable ssaSink0 | | SSA.cs:25:15:25:22 | access to local variable ssaSink1 | | SSA.cs:43:15:43:22 | access to local variable ssaSink2 | diff --git a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected index 8dd765a23cd..4cb33d841cb 100644 --- a/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected +++ b/csharp/ql/test/library-tests/dataflow/local/TaintTrackingStep.expected @@ -24,9 +24,8 @@ | Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) | | Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) | | Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i | -| LocalDataFlow.cs:49:23:49:23 | this | LocalDataFlow.cs:299:39:299:51 | this access | | LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:49:30:49:30 | b | -| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b | +| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:85:21:85:21 | access to parameter b | | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 | | LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | | LocalDataFlow.cs:53:15:53:19 | [post] access to local variable sink0 | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | @@ -41,713 +40,508 @@ | LocalDataFlow.cs:61:9:61:22 | ... + ... | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | | LocalDataFlow.cs:61:9:61:22 | SSA def(sink1) | LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | | LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:61:9:61:22 | ... + ... | -| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | -| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | -| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | +| LocalDataFlow.cs:61:18:61:22 | access to local variable sink0 | LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | +| LocalDataFlow.cs:62:15:62:19 | [post] access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | +| LocalDataFlow.cs:62:15:62:19 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | | LocalDataFlow.cs:65:9:65:16 | access to local variable nonSink0 | LocalDataFlow.cs:65:9:65:25 | ... + ... | | LocalDataFlow.cs:65:9:65:25 | ... + ... | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | | LocalDataFlow.cs:65:9:65:25 | SSA def(nonSink0) | LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | | LocalDataFlow.cs:65:21:65:25 | "abc" | LocalDataFlow.cs:65:9:65:25 | ... + ... | -| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | -| LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:69:21:69:51 | object creation of type Dictionary | LocalDataFlow.cs:69:13:69:51 | SSA def(sink2) | -| LocalDataFlow.cs:70:9:70:13 | [post] access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:70:9:70:16 | access to indexer | -| LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | LocalDataFlow.cs:71:15:71:19 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:70:9:70:13 | access to local variable sink2 | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:70:9:70:16 | access to indexer | -| LocalDataFlow.cs:70:23:70:27 | access to local variable sink1 | LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | -| LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:74:24:74:55 | object creation of type Dictionary | LocalDataFlow.cs:74:13:74:55 | SSA def(nonSink1) | -| LocalDataFlow.cs:75:9:75:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:75:9:75:20 | access to indexer | -| LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | [post] access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:75:9:75:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:75:24:75:31 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:76:9:76:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:76:9:76:23 | access to indexer | -| LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | LocalDataFlow.cs:77:15:77:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:76:18:76:22 | [post] access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:18:76:22 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | -| LocalDataFlow.cs:76:27:76:28 | "" | LocalDataFlow.cs:76:9:76:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:80:21:80:32 | ... + ... | -| LocalDataFlow.cs:80:21:80:25 | access to local variable sink1 | LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | -| LocalDataFlow.cs:80:21:80:32 | ... + ... | LocalDataFlow.cs:80:13:80:32 | SSA def(sink5) | -| LocalDataFlow.cs:80:29:80:32 | "ok" | LocalDataFlow.cs:80:21:80:32 | ... + ... | -| LocalDataFlow.cs:81:15:81:19 | [post] access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:81:15:81:19 | access to local variable sink5 | LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | -| LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:84:20:84:27 | access to local variable nonSink0 | LocalDataFlow.cs:84:20:84:36 | ... + ... | -| LocalDataFlow.cs:84:20:84:36 | ... + ... | LocalDataFlow.cs:84:9:84:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:84:31:84:36 | "test" | LocalDataFlow.cs:84:20:84:36 | ... + ... | -| LocalDataFlow.cs:85:15:85:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:85:15:85:22 | access to local variable nonSink0 | LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | -| LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | -| LocalDataFlow.cs:88:22:88:26 | access to local variable sink5 | LocalDataFlow.cs:88:13:88:27 | SSA def(sink6) | -| LocalDataFlow.cs:89:15:89:19 | [post] access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:89:15:89:19 | access to local variable sink6 | LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | -| LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | LocalDataFlow.cs:93:15:93:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:92:21:92:28 | access to local variable nonSink0 | LocalDataFlow.cs:92:9:92:29 | SSA def(nonSink0) | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | -| LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): false] access to parameter b | -| LocalDataFlow.cs:96:21:96:21 | access to parameter b | LocalDataFlow.cs:100:20:100:20 | [b (line 49): true] access to parameter b | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): false] SSA def(sink7) | -| LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | LocalDataFlow.cs:96:13:96:35 | [b (line 49): true] SSA def(sink7) | -| LocalDataFlow.cs:96:25:96:27 | [b (line 49): true] "a" | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:96:31:96:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:96:21:96:35 | ... ? ... : ... | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:97:15:97:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | -| LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:100:9:100:36 | SSA phi(sink7) | LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:100:9:100:36 | SSA def(nonSink0) | -| LocalDataFlow.cs:100:24:100:28 | "abc" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): true] ... ? ... : ... | -| LocalDataFlow.cs:100:32:100:36 | "def" | LocalDataFlow.cs:100:20:100:36 | [b (line 49): false] ... ? ... : ... | -| LocalDataFlow.cs:101:15:101:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:101:15:101:22 | access to local variable nonSink0 | LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | -| LocalDataFlow.cs:104:21:104:33 | (...) ... | LocalDataFlow.cs:104:13:104:33 | SSA def(sink8) | -| LocalDataFlow.cs:104:29:104:33 | access to local variable sink7 | LocalDataFlow.cs:104:21:104:33 | (...) ... | -| LocalDataFlow.cs:105:15:105:19 | [post] access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:105:15:105:19 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | -| LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | LocalDataFlow.cs:109:15:109:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:108:24:108:39 | (...) ... | LocalDataFlow.cs:108:13:108:39 | SSA def(nonSink3) | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:108:24:108:39 | (...) ... | -| LocalDataFlow.cs:108:32:108:39 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:112:21:112:35 | ... as ... | -| LocalDataFlow.cs:112:21:112:25 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | -| LocalDataFlow.cs:112:21:112:35 | ... as ... | LocalDataFlow.cs:112:13:112:35 | SSA def(sink9) | -| LocalDataFlow.cs:113:15:113:19 | [post] access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:113:15:113:19 | access to local variable sink9 | LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | -| LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | LocalDataFlow.cs:117:15:117:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:116:20:116:37 | ... as ... | -| LocalDataFlow.cs:116:20:116:27 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:116:20:116:37 | ... as ... | LocalDataFlow.cs:116:9:116:37 | SSA def(nonSink3) | -| LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | -| LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | LocalDataFlow.cs:120:13:120:43 | SSA def(sink10) | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:43 | array creation of type Object[] | -| LocalDataFlow.cs:120:37:120:41 | access to local variable sink9 | LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | -| LocalDataFlow.cs:121:15:121:20 | [post] access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:121:15:121:20 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | -| LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | -| LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | LocalDataFlow.cs:124:13:124:42 | SSA def(nonSink4) | -| LocalDataFlow.cs:124:39:124:40 | 42 | LocalDataFlow.cs:124:39:124:40 | (...) ... | -| LocalDataFlow.cs:124:39:124:40 | (...) ... | LocalDataFlow.cs:124:24:124:42 | array creation of type Object[] | -| LocalDataFlow.cs:125:15:125:22 | [post] access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:125:15:125:22 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | -| LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | -| LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | LocalDataFlow.cs:128:13:128:69 | SSA def(sink11) | -| LocalDataFlow.cs:128:61:128:65 | [post] access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:128:22:128:69 | object creation of type Dictionary | -| LocalDataFlow.cs:128:61:128:65 | access to local variable sink9 | LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | -| LocalDataFlow.cs:129:15:129:20 | [post] access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:129:15:129:20 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | -| LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | LocalDataFlow.cs:132:9:132:67 | SSA def(nonSink1) | -| LocalDataFlow.cs:132:55:132:59 | [post] access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:55:132:59 | access to local variable sink9 | LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | -| LocalDataFlow.cs:132:62:132:63 | "" | LocalDataFlow.cs:132:20:132:67 | object creation of type Dictionary | -| LocalDataFlow.cs:133:15:133:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:133:15:133:22 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | LocalDataFlow.cs:137:15:137:20 | access to local variable sink14 | -| LocalDataFlow.cs:136:22:136:27 | [post] access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:136:22:136:55 | call to method First | -| LocalDataFlow.cs:136:22:136:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | -| LocalDataFlow.cs:136:22:136:55 | call to method First | LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:35:136:35 | x | -| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x | -| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value | -| LocalDataFlow.cs:136:40:136:46 | access to property Value | LocalDataFlow.cs:136:40:136:54 | ... != ... | -| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 | -| LocalDataFlow.cs:140:20:140:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:55 | call to method First | -| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:140:20:140:55 | (...) ... | LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | -| LocalDataFlow.cs:140:20:140:55 | call to method First | LocalDataFlow.cs:140:20:140:55 | (...) ... | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:35:140:35 | x | -| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x | -| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value | -| LocalDataFlow.cs:140:40:140:46 | access to property Value | LocalDataFlow.cs:140:40:140:54 | ... != ... | -| LocalDataFlow.cs:141:15:141:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | -| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | -| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | -| LocalDataFlow.cs:144:34:144:38 | [post] access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:144:22:144:39 | call to method Parse | -| LocalDataFlow.cs:144:34:144:38 | access to local variable sink9 | LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | -| LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | -| LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | LocalDataFlow.cs:148:15:148:20 | access to local variable sink16 | -| LocalDataFlow.cs:147:22:147:56 | call to method TryParse | LocalDataFlow.cs:147:13:147:56 | SSA def(sink16) | -| LocalDataFlow.cs:147:37:147:41 | [post] access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:147:22:147:56 | call to method TryParse | -| LocalDataFlow.cs:147:37:147:41 | access to local variable sink9 | LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | -| LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | LocalDataFlow.cs:150:15:150:20 | access to local variable sink17 | -| LocalDataFlow.cs:149:22:149:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:149:22:149:49 | call to method Replace | -| LocalDataFlow.cs:149:22:149:29 | access to local variable nonSink0 | LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | -| LocalDataFlow.cs:149:22:149:49 | call to method Replace | LocalDataFlow.cs:149:13:149:49 | SSA def(sink17) | -| LocalDataFlow.cs:149:44:149:48 | [post] access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:149:22:149:49 | call to method Replace | -| LocalDataFlow.cs:149:44:149:48 | access to local variable sink9 | LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | -| LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | -| LocalDataFlow.cs:151:22:151:51 | call to method Format | LocalDataFlow.cs:151:13:151:51 | SSA def(sink18) | -| LocalDataFlow.cs:151:36:151:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:151:22:151:51 | call to method Format | -| LocalDataFlow.cs:151:36:151:43 | access to local variable nonSink0 | LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:151:46:151:50 | [post] access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:151:22:151:51 | call to method Format | -| LocalDataFlow.cs:151:46:151:50 | access to local variable sink9 | LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | -| LocalDataFlow.cs:152:15:152:20 | [post] access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:152:15:152:20 | access to local variable sink18 | LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | -| LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | LocalDataFlow.cs:154:15:154:20 | access to local variable sink19 | -| LocalDataFlow.cs:153:22:153:52 | call to method Format | LocalDataFlow.cs:153:13:153:52 | SSA def(sink19) | -| LocalDataFlow.cs:153:36:153:41 | access to local variable sink18 | LocalDataFlow.cs:153:22:153:52 | call to method Format | -| LocalDataFlow.cs:153:44:153:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:153:22:153:52 | call to method Format | -| LocalDataFlow.cs:153:44:153:51 | access to local variable nonSink0 | LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | LocalDataFlow.cs:156:15:156:20 | access to local variable sink45 | -| LocalDataFlow.cs:155:22:155:38 | call to method Parse | LocalDataFlow.cs:155:13:155:38 | SSA def(sink45) | -| LocalDataFlow.cs:155:33:155:37 | [post] access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:155:22:155:38 | call to method Parse | -| LocalDataFlow.cs:155:33:155:37 | access to local variable sink9 | LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | -| LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | -| LocalDataFlow.cs:158:22:158:56 | call to method TryParse | LocalDataFlow.cs:158:13:158:56 | SSA def(sink46) | -| LocalDataFlow.cs:158:36:158:40 | [post] access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:158:22:158:56 | call to method TryParse | -| LocalDataFlow.cs:158:36:158:40 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | -| LocalDataFlow.cs:159:15:159:20 | access to local variable sink46 | LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | -| LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | -| LocalDataFlow.cs:160:22:160:43 | call to method ToByte | LocalDataFlow.cs:160:13:160:43 | SSA def(sink47) | -| LocalDataFlow.cs:160:37:160:42 | access to local variable sink46 | LocalDataFlow.cs:160:22:160:43 | call to method ToByte | -| LocalDataFlow.cs:161:15:161:20 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | -| LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | -| LocalDataFlow.cs:162:22:162:46 | call to method Concat | LocalDataFlow.cs:162:13:162:46 | SSA def(sink49) | -| LocalDataFlow.cs:162:36:162:37 | "" | LocalDataFlow.cs:162:22:162:46 | call to method Concat | -| LocalDataFlow.cs:162:40:162:45 | (...) ... | LocalDataFlow.cs:162:22:162:46 | call to method Concat | -| LocalDataFlow.cs:162:40:162:45 | access to local variable sink47 | LocalDataFlow.cs:162:40:162:45 | (...) ... | -| LocalDataFlow.cs:163:15:163:20 | [post] access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:163:15:163:20 | access to local variable sink49 | LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | -| LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | -| LocalDataFlow.cs:164:22:164:40 | call to method Copy | LocalDataFlow.cs:164:13:164:40 | SSA def(sink50) | -| LocalDataFlow.cs:164:34:164:39 | access to local variable sink49 | LocalDataFlow.cs:164:22:164:40 | call to method Copy | -| LocalDataFlow.cs:165:15:165:20 | [post] access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:165:15:165:20 | access to local variable sink50 | LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | -| LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | -| LocalDataFlow.cs:166:22:166:54 | call to method Join | LocalDataFlow.cs:166:13:166:54 | SSA def(sink51) | -| LocalDataFlow.cs:166:34:166:37 | ", " | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:40:166:41 | "" | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:44:166:49 | access to local variable sink50 | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:166:52:166:53 | "" | LocalDataFlow.cs:166:22:166:54 | call to method Join | -| LocalDataFlow.cs:167:15:167:20 | [post] access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:167:15:167:20 | access to local variable sink51 | LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | -| LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | LocalDataFlow.cs:169:15:169:20 | access to local variable sink52 | -| LocalDataFlow.cs:168:22:168:23 | "" | LocalDataFlow.cs:168:22:168:41 | call to method Insert | -| LocalDataFlow.cs:168:22:168:41 | call to method Insert | LocalDataFlow.cs:168:13:168:41 | SSA def(sink52) | -| LocalDataFlow.cs:168:35:168:40 | access to local variable sink51 | LocalDataFlow.cs:168:22:168:41 | call to method Insert | -| LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | LocalDataFlow.cs:173:15:173:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:172:20:172:40 | call to method Parse | LocalDataFlow.cs:172:9:172:40 | SSA def(nonSink2) | -| LocalDataFlow.cs:172:32:172:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:172:20:172:40 | call to method Parse | -| LocalDataFlow.cs:172:32:172:39 | access to local variable nonSink0 | LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | LocalDataFlow.cs:175:15:175:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:174:24:174:61 | call to method TryParse | LocalDataFlow.cs:174:13:174:61 | SSA def(nonSink7) | -| LocalDataFlow.cs:174:39:174:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:174:24:174:61 | call to method TryParse | -| LocalDataFlow.cs:174:39:174:46 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:50 | call to method Replace | -| LocalDataFlow.cs:176:20:176:27 | access to local variable nonSink0 | LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:176:20:176:50 | call to method Replace | LocalDataFlow.cs:176:9:176:50 | SSA def(nonSink0) | -| LocalDataFlow.cs:176:42:176:49 | access to local variable nonSink0 | LocalDataFlow.cs:176:20:176:50 | call to method Replace | -| LocalDataFlow.cs:177:15:177:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:177:15:177:22 | access to local variable nonSink0 | LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:20:178:52 | call to method Format | LocalDataFlow.cs:178:9:178:52 | SSA def(nonSink0) | -| LocalDataFlow.cs:178:34:178:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:20:178:52 | call to method Format | -| LocalDataFlow.cs:178:34:178:41 | access to local variable nonSink0 | LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | -| LocalDataFlow.cs:178:44:178:51 | access to local variable nonSink0 | LocalDataFlow.cs:178:20:178:52 | call to method Format | -| LocalDataFlow.cs:179:15:179:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:179:15:179:22 | access to local variable nonSink0 | LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | LocalDataFlow.cs:181:15:181:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:180:20:180:39 | call to method Parse | LocalDataFlow.cs:180:9:180:39 | SSA def(nonSink7) | -| LocalDataFlow.cs:180:31:180:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:180:20:180:39 | call to method Parse | -| LocalDataFlow.cs:180:31:180:38 | access to local variable nonSink0 | LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | -| LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:182:20:182:57 | call to method TryParse | LocalDataFlow.cs:182:9:182:57 | SSA def(nonSink7) | -| LocalDataFlow.cs:182:34:182:41 | access to local variable nonSink0 | LocalDataFlow.cs:182:20:182:57 | call to method TryParse | -| LocalDataFlow.cs:183:15:183:22 | access to local variable nonSink7 | LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | -| LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | LocalDataFlow.cs:185:15:185:23 | access to local variable nonSink14 | -| LocalDataFlow.cs:184:25:184:48 | call to method ToByte | LocalDataFlow.cs:184:13:184:48 | SSA def(nonSink14) | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:184:25:184:48 | call to method ToByte | -| LocalDataFlow.cs:184:40:184:47 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | -| LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:186:20:186:46 | call to method Concat | LocalDataFlow.cs:186:9:186:46 | SSA def(nonSink0) | -| LocalDataFlow.cs:186:34:186:35 | "" | LocalDataFlow.cs:186:20:186:46 | call to method Concat | -| LocalDataFlow.cs:186:38:186:45 | (...) ... | LocalDataFlow.cs:186:20:186:46 | call to method Concat | -| LocalDataFlow.cs:186:38:186:45 | access to local variable nonSink7 | LocalDataFlow.cs:186:38:186:45 | (...) ... | -| LocalDataFlow.cs:187:15:187:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:187:15:187:22 | access to local variable nonSink0 | LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:188:20:188:40 | call to method Copy | LocalDataFlow.cs:188:9:188:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:188:32:188:39 | access to local variable nonSink0 | LocalDataFlow.cs:188:20:188:40 | call to method Copy | -| LocalDataFlow.cs:189:15:189:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:189:15:189:22 | access to local variable nonSink0 | LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:190:20:190:54 | call to method Join | LocalDataFlow.cs:190:9:190:54 | SSA def(nonSink0) | -| LocalDataFlow.cs:190:32:190:35 | ", " | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:38:190:39 | "" | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:42:190:49 | access to local variable nonSink0 | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:190:52:190:53 | "" | LocalDataFlow.cs:190:20:190:54 | call to method Join | -| LocalDataFlow.cs:191:15:191:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:191:15:191:22 | access to local variable nonSink0 | LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | LocalDataFlow.cs:193:15:193:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:192:20:192:21 | "" | LocalDataFlow.cs:192:20:192:41 | call to method Insert | -| LocalDataFlow.cs:192:20:192:41 | call to method Insert | LocalDataFlow.cs:192:9:192:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:192:33:192:40 | access to local variable nonSink0 | LocalDataFlow.cs:192:20:192:41 | call to method Insert | -| LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | -| LocalDataFlow.cs:196:22:196:27 | access to local variable sink15 | LocalDataFlow.cs:196:22:196:32 | ... > ... | -| LocalDataFlow.cs:196:22:196:32 | ... > ... | LocalDataFlow.cs:196:13:196:32 | SSA def(sink20) | -| LocalDataFlow.cs:197:15:197:20 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | -| LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | LocalDataFlow.cs:199:15:199:20 | access to local variable sink21 | -| LocalDataFlow.cs:198:22:198:26 | access to local variable sink9 | LocalDataFlow.cs:198:22:198:40 | call to method Equals | -| LocalDataFlow.cs:198:22:198:40 | call to method Equals | LocalDataFlow.cs:198:13:198:40 | SSA def(sink21) | -| LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | LocalDataFlow.cs:201:15:201:20 | access to local variable sink22 | -| LocalDataFlow.cs:200:22:200:26 | [post] access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:200:22:200:45 | call to method Equals | -| LocalDataFlow.cs:200:22:200:26 | access to local variable sink8 | LocalDataFlow.cs:206:20:206:24 | access to local variable sink8 | -| LocalDataFlow.cs:200:22:200:45 | call to method Equals | LocalDataFlow.cs:200:13:200:45 | SSA def(sink22) | -| LocalDataFlow.cs:200:43:200:44 | 41 | LocalDataFlow.cs:200:35:200:44 | (...) ... | -| LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | LocalDataFlow.cs:205:15:205:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:204:20:204:24 | [post] access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:24 | access to local variable sink0 | LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | -| LocalDataFlow.cs:204:20:204:38 | call to method Equals | LocalDataFlow.cs:204:9:204:38 | SSA def(nonSink7) | -| LocalDataFlow.cs:204:33:204:37 | [post] access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:204:33:204:37 | access to local variable sink1 | LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | -| LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:206:20:206:41 | call to method Equals | LocalDataFlow.cs:206:9:206:41 | SSA def(nonSink7) | -| LocalDataFlow.cs:207:15:207:22 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | -| LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | -| LocalDataFlow.cs:210:22:210:27 | access to local variable sink11 | LocalDataFlow.cs:210:22:210:31 | access to indexer | -| LocalDataFlow.cs:210:22:210:31 | access to indexer | LocalDataFlow.cs:210:13:210:31 | SSA def(sink23) | -| LocalDataFlow.cs:211:15:211:20 | [post] access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:211:15:211:20 | access to local variable sink23 | LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | -| LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:214:20:214:27 | [post] access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:31 | access to indexer | -| LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:214:20:214:31 | access to indexer | LocalDataFlow.cs:214:9:214:31 | SSA def(nonSink0) | -| LocalDataFlow.cs:215:15:215:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:215:15:215:22 | access to local variable nonSink0 | LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | -| LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | LocalDataFlow.cs:219:15:219:20 | access to local variable sink24 | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:218:22:218:30 | access to array element | -| LocalDataFlow.cs:218:22:218:27 | access to local variable sink10 | LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | -| LocalDataFlow.cs:218:22:218:30 | access to array element | LocalDataFlow.cs:218:13:218:30 | SSA def(sink24) | -| LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | LocalDataFlow.cs:223:15:223:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:222:20:222:30 | access to array element | -| LocalDataFlow.cs:222:20:222:27 | access to local variable nonSink4 | LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | -| LocalDataFlow.cs:222:20:222:30 | access to array element | LocalDataFlow.cs:222:9:222:30 | SSA def(nonSink3) | -| LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | LocalDataFlow.cs:227:15:227:20 | access to local variable sink25 | -| LocalDataFlow.cs:226:22:226:27 | access to local variable sink20 | LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | -| LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | LocalDataFlow.cs:226:13:226:36 | SSA def(sink25) | -| LocalDataFlow.cs:226:32:226:36 | false | LocalDataFlow.cs:226:22:226:36 | ... \|\| ... | -| LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | LocalDataFlow.cs:231:15:231:22 | access to local variable nonSink7 | -| LocalDataFlow.cs:230:20:230:27 | access to local variable nonSink7 | LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | -| LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | LocalDataFlow.cs:230:9:230:36 | SSA def(nonSink7) | -| LocalDataFlow.cs:230:32:230:36 | false | LocalDataFlow.cs:230:20:230:36 | ... \|\| ... | -| LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | -| LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | LocalDataFlow.cs:234:13:234:43 | SSA def(sink26) | -| LocalDataFlow.cs:234:37:234:42 | access to local variable sink23 | LocalDataFlow.cs:234:22:234:43 | object creation of type Uri | -| LocalDataFlow.cs:235:15:235:20 | [post] access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:235:15:235:20 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | LocalDataFlow.cs:237:15:237:20 | access to local variable sink27 | -| LocalDataFlow.cs:236:22:236:27 | [post] access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:236:22:236:38 | call to method ToString | -| LocalDataFlow.cs:236:22:236:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | -| LocalDataFlow.cs:236:22:236:38 | call to method ToString | LocalDataFlow.cs:236:13:236:38 | SSA def(sink27) | -| LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | LocalDataFlow.cs:239:15:239:20 | access to local variable sink28 | -| LocalDataFlow.cs:238:22:238:27 | [post] access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | -| LocalDataFlow.cs:238:22:238:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | -| LocalDataFlow.cs:238:22:238:40 | access to property PathAndQuery | LocalDataFlow.cs:238:13:238:40 | SSA def(sink28) | -| LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | LocalDataFlow.cs:241:15:241:20 | access to local variable sink29 | -| LocalDataFlow.cs:240:22:240:27 | [post] access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:240:22:240:33 | access to property Query | -| LocalDataFlow.cs:240:22:240:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | -| LocalDataFlow.cs:240:22:240:33 | access to property Query | LocalDataFlow.cs:240:13:240:33 | SSA def(sink29) | -| LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | -| LocalDataFlow.cs:242:22:242:27 | access to local variable sink26 | LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | -| LocalDataFlow.cs:242:22:242:42 | access to property OriginalString | LocalDataFlow.cs:242:13:242:42 | SSA def(sink30) | -| LocalDataFlow.cs:243:15:243:20 | [post] access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:243:15:243:20 | access to local variable sink30 | LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | -| LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | -| LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | LocalDataFlow.cs:246:13:246:47 | SSA def(nonSink8) | -| LocalDataFlow.cs:246:39:246:46 | access to local variable nonSink0 | LocalDataFlow.cs:246:24:246:47 | object creation of type Uri | -| LocalDataFlow.cs:247:15:247:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:247:15:247:22 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | LocalDataFlow.cs:249:15:249:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:248:20:248:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:248:20:248:38 | call to method ToString | -| LocalDataFlow.cs:248:20:248:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:248:20:248:38 | call to method ToString | LocalDataFlow.cs:248:9:248:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | LocalDataFlow.cs:251:15:251:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:250:20:250:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | -| LocalDataFlow.cs:250:20:250:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:250:20:250:40 | access to property PathAndQuery | LocalDataFlow.cs:250:9:250:40 | SSA def(nonSink0) | -| LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | LocalDataFlow.cs:253:15:253:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:252:20:252:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:252:20:252:33 | access to property Query | -| LocalDataFlow.cs:252:20:252:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | -| LocalDataFlow.cs:252:20:252:33 | access to property Query | LocalDataFlow.cs:252:9:252:33 | SSA def(nonSink0) | -| LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:254:20:254:27 | access to local variable nonSink8 | LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | -| LocalDataFlow.cs:254:20:254:42 | access to property OriginalString | LocalDataFlow.cs:254:9:254:42 | SSA def(nonSink0) | -| LocalDataFlow.cs:255:15:255:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:255:15:255:22 | access to local variable nonSink0 | LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | -| LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | -| LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | LocalDataFlow.cs:258:13:258:55 | SSA def(sink31) | -| LocalDataFlow.cs:258:49:258:54 | access to local variable sink30 | LocalDataFlow.cs:258:22:258:55 | object creation of type StringReader | -| LocalDataFlow.cs:259:15:259:20 | [post] access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:259:15:259:20 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | -| LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | -| LocalDataFlow.cs:260:22:260:27 | access to local variable sink31 | LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | -| LocalDataFlow.cs:260:22:260:39 | call to method ReadToEnd | LocalDataFlow.cs:260:13:260:39 | SSA def(sink32) | -| LocalDataFlow.cs:261:15:261:20 | [post] access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:261:15:261:20 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | -| LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | -| LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | LocalDataFlow.cs:264:13:264:59 | SSA def(nonSink9) | -| LocalDataFlow.cs:264:51:264:58 | access to local variable nonSink0 | LocalDataFlow.cs:264:24:264:59 | object creation of type StringReader | -| LocalDataFlow.cs:265:15:265:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:265:15:265:22 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | -| LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:266:20:266:27 | access to local variable nonSink9 | LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | -| LocalDataFlow.cs:266:20:266:39 | call to method ReadToEnd | LocalDataFlow.cs:266:9:266:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:267:15:267:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:267:15:267:22 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | -| LocalDataFlow.cs:270:22:270:127 | (...) ... | LocalDataFlow.cs:270:13:270:127 | SSA def(sink33) | -| LocalDataFlow.cs:270:30:270:35 | access to local variable sink32 | LocalDataFlow.cs:270:30:270:48 | call to method Substring | -| LocalDataFlow.cs:270:30:270:48 | call to method Substring | LocalDataFlow.cs:270:30:270:67 | call to method ToLowerInvariant | -| LocalDataFlow.cs:270:30:270:67 | call to method ToLowerInvariant | LocalDataFlow.cs:270:30:270:77 | call to method ToUpper | -| LocalDataFlow.cs:270:30:270:77 | call to method ToUpper | LocalDataFlow.cs:270:30:270:87 | call to method Trim | -| LocalDataFlow.cs:270:30:270:87 | call to method Trim | LocalDataFlow.cs:270:30:270:105 | call to method Replace | -| LocalDataFlow.cs:270:30:270:105 | call to method Replace | LocalDataFlow.cs:270:30:270:119 | call to method Insert | -| LocalDataFlow.cs:270:30:270:119 | call to method Insert | LocalDataFlow.cs:270:30:270:127 | call to method Clone | -| LocalDataFlow.cs:270:30:270:127 | call to method Clone | LocalDataFlow.cs:270:22:270:127 | (...) ... | -| LocalDataFlow.cs:270:102:270:104 | "b" | LocalDataFlow.cs:270:30:270:105 | call to method Replace | -| LocalDataFlow.cs:270:117:270:118 | "" | LocalDataFlow.cs:270:30:270:119 | call to method Insert | -| LocalDataFlow.cs:271:15:271:20 | [post] access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:271:15:271:20 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | -| LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | LocalDataFlow.cs:273:15:273:20 | access to local variable sink48 | -| LocalDataFlow.cs:272:22:272:27 | [post] access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:272:22:272:39 | call to method Normalize | -| LocalDataFlow.cs:272:22:272:27 | access to local variable sink33 | LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | -| LocalDataFlow.cs:272:22:272:39 | call to method Normalize | LocalDataFlow.cs:272:22:272:52 | call to method Remove | -| LocalDataFlow.cs:272:22:272:52 | call to method Remove | LocalDataFlow.cs:272:22:272:63 | call to method Split | -| LocalDataFlow.cs:272:22:272:63 | call to method Split | LocalDataFlow.cs:272:13:272:63 | SSA def(sink48) | -| LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:276:20:276:127 | (...) ... | LocalDataFlow.cs:276:9:276:127 | SSA def(nonSink0) | -| LocalDataFlow.cs:276:28:276:35 | access to local variable nonSink0 | LocalDataFlow.cs:276:28:276:48 | call to method Substring | -| LocalDataFlow.cs:276:28:276:48 | call to method Substring | LocalDataFlow.cs:276:28:276:67 | call to method ToLowerInvariant | -| LocalDataFlow.cs:276:28:276:67 | call to method ToLowerInvariant | LocalDataFlow.cs:276:28:276:77 | call to method ToUpper | -| LocalDataFlow.cs:276:28:276:77 | call to method ToUpper | LocalDataFlow.cs:276:28:276:87 | call to method Trim | -| LocalDataFlow.cs:276:28:276:87 | call to method Trim | LocalDataFlow.cs:276:28:276:105 | call to method Replace | -| LocalDataFlow.cs:276:28:276:105 | call to method Replace | LocalDataFlow.cs:276:28:276:119 | call to method Insert | -| LocalDataFlow.cs:276:28:276:119 | call to method Insert | LocalDataFlow.cs:276:28:276:127 | call to method Clone | -| LocalDataFlow.cs:276:28:276:127 | call to method Clone | LocalDataFlow.cs:276:20:276:127 | (...) ... | -| LocalDataFlow.cs:276:102:276:104 | "b" | LocalDataFlow.cs:276:28:276:105 | call to method Replace | -| LocalDataFlow.cs:276:117:276:118 | "" | LocalDataFlow.cs:276:28:276:119 | call to method Insert | -| LocalDataFlow.cs:277:15:277:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:277:15:277:22 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | LocalDataFlow.cs:279:15:279:23 | access to local variable nonSink15 | -| LocalDataFlow.cs:278:25:278:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:278:25:278:44 | call to method Normalize | -| LocalDataFlow.cs:278:25:278:32 | access to local variable nonSink0 | LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | -| LocalDataFlow.cs:278:25:278:44 | call to method Normalize | LocalDataFlow.cs:278:25:278:57 | call to method Remove | -| LocalDataFlow.cs:278:25:278:57 | call to method Remove | LocalDataFlow.cs:278:25:278:68 | call to method Split | -| LocalDataFlow.cs:278:25:278:68 | call to method Split | LocalDataFlow.cs:278:13:278:68 | SSA def(nonSink15) | -| LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | -| LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | LocalDataFlow.cs:282:13:282:46 | SSA def(sink34) | -| LocalDataFlow.cs:282:40:282:45 | access to local variable sink33 | LocalDataFlow.cs:282:22:282:46 | object creation of type StringBuilder | -| LocalDataFlow.cs:283:15:283:20 | [post] access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:283:15:283:20 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | -| LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | -| LocalDataFlow.cs:284:22:284:27 | access to local variable sink34 | LocalDataFlow.cs:284:22:284:38 | call to method ToString | -| LocalDataFlow.cs:284:22:284:38 | call to method ToString | LocalDataFlow.cs:284:13:284:38 | SSA def(sink35) | -| LocalDataFlow.cs:285:15:285:20 | [post] access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:285:15:285:20 | access to local variable sink35 | LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | -| LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | LocalDataFlow.cs:286:13:286:42 | SSA def(sink36) | -| LocalDataFlow.cs:286:40:286:41 | "" | LocalDataFlow.cs:286:22:286:42 | object creation of type StringBuilder | -| LocalDataFlow.cs:287:9:287:14 | [post] access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | LocalDataFlow.cs:288:15:288:20 | access to local variable sink36 | -| LocalDataFlow.cs:287:27:287:32 | access to local variable sink35 | LocalDataFlow.cs:287:9:287:14 | access to local variable sink36 | -| LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | LocalDataFlow.cs:291:13:291:51 | SSA def(nonSink10) | -| LocalDataFlow.cs:291:43:291:50 | access to local variable nonSink0 | LocalDataFlow.cs:291:25:291:51 | object creation of type StringBuilder | -| LocalDataFlow.cs:292:15:292:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:292:15:292:23 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:293:20:293:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:293:20:293:39 | call to method ToString | -| LocalDataFlow.cs:293:20:293:28 | access to local variable nonSink10 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:293:20:293:39 | call to method ToString | LocalDataFlow.cs:293:9:293:39 | SSA def(nonSink0) | -| LocalDataFlow.cs:294:15:294:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:294:15:294:22 | access to local variable nonSink0 | LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | -| LocalDataFlow.cs:295:9:295:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | LocalDataFlow.cs:296:15:296:23 | access to local variable nonSink10 | -| LocalDataFlow.cs:295:30:295:37 | access to local variable nonSink0 | LocalDataFlow.cs:295:9:295:17 | access to local variable nonSink10 | -| LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | -| LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | LocalDataFlow.cs:299:13:299:52 | SSA def(sink40) | -| LocalDataFlow.cs:299:39:299:51 | [output] delegate creation of type Func | LocalDataFlow.cs:299:22:299:52 | object creation of type Lazy | -| LocalDataFlow.cs:299:39:299:51 | this access | LocalDataFlow.cs:309:42:309:57 | this access | -| LocalDataFlow.cs:300:15:300:20 | [post] access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:300:15:300:20 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | -| LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | LocalDataFlow.cs:302:15:302:20 | access to local variable sink41 | -| LocalDataFlow.cs:301:22:301:27 | access to local variable sink40 | LocalDataFlow.cs:301:22:301:33 | access to property Value | -| LocalDataFlow.cs:301:22:301:33 | access to property Value | LocalDataFlow.cs:301:13:301:33 | SSA def(sink41) | -| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | -| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | -| LocalDataFlow.cs:303:39:303:58 | [output] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy | -| LocalDataFlow.cs:304:15:304:20 | [post] access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | -| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 | -| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value | -| LocalDataFlow.cs:305:22:305:33 | access to property Value | LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | -| LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | LocalDataFlow.cs:309:13:309:58 | SSA def(nonSink12) | -| LocalDataFlow.cs:309:42:309:57 | [output] delegate creation of type Func | LocalDataFlow.cs:309:25:309:58 | object creation of type Lazy | -| LocalDataFlow.cs:310:15:310:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:310:15:310:23 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | LocalDataFlow.cs:312:15:312:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:311:20:311:28 | access to local variable nonSink12 | LocalDataFlow.cs:311:20:311:34 | access to property Value | -| LocalDataFlow.cs:311:20:311:34 | access to property Value | LocalDataFlow.cs:311:9:311:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | -| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | -| LocalDataFlow.cs:313:38:313:45 | [output] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy | -| LocalDataFlow.cs:314:15:314:23 | [post] access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | -| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value | -| LocalDataFlow.cs:315:20:315:34 | access to property Value | LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:316:15:316:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 | LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | -| LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:319:21:319:49 | object creation of type Dictionary | LocalDataFlow.cs:319:13:319:49 | SSA def(sink3) | -| LocalDataFlow.cs:320:9:320:13 | [post] access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | [post] access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:320:9:320:13 | access to local variable sink3 | -| LocalDataFlow.cs:320:22:320:26 | access to local variable sink1 | LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | -| LocalDataFlow.cs:321:15:321:19 | [post] access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:321:15:321:19 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | -| LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | -| LocalDataFlow.cs:322:22:322:26 | [post] access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:322:22:322:33 | access to property Values | -| LocalDataFlow.cs:322:22:322:26 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | -| LocalDataFlow.cs:322:22:322:33 | access to property Values | LocalDataFlow.cs:322:13:322:33 | SSA def(sink12) | -| LocalDataFlow.cs:323:15:323:20 | [post] access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:323:15:323:20 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | -| LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | LocalDataFlow.cs:325:15:325:20 | access to local variable sink13 | -| LocalDataFlow.cs:324:22:324:27 | access to local variable sink12 | LocalDataFlow.cs:324:22:324:37 | call to method Reverse | -| LocalDataFlow.cs:324:22:324:37 | call to method Reverse | LocalDataFlow.cs:324:13:324:37 | SSA def(sink13) | -| LocalDataFlow.cs:328:9:328:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:328:26:328:33 | access to local variable nonSink0 | LocalDataFlow.cs:328:9:328:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | [post] access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | -| LocalDataFlow.cs:329:22:329:26 | [post] access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:22:329:26 | access to local variable sink1 | LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | -| LocalDataFlow.cs:329:29:329:30 | "" | LocalDataFlow.cs:329:9:329:16 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | [post] access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:330:15:330:22 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | -| LocalDataFlow.cs:331:24:331:31 | [post] access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:331:24:331:38 | access to property Values | -| LocalDataFlow.cs:331:24:331:31 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | -| LocalDataFlow.cs:331:24:331:38 | access to property Values | LocalDataFlow.cs:331:13:331:38 | SSA def(nonSink5) | -| LocalDataFlow.cs:332:15:332:22 | [post] access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:332:15:332:22 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | -| LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | LocalDataFlow.cs:334:15:334:22 | access to local variable nonSink6 | -| LocalDataFlow.cs:333:24:333:31 | access to local variable nonSink5 | LocalDataFlow.cs:333:24:333:41 | call to method Reverse | -| LocalDataFlow.cs:333:24:333:41 | call to method Reverse | LocalDataFlow.cs:333:13:333:41 | SSA def(nonSink6) | -| LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:337:13:337:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:337:35:337:52 | object creation of type DataContract | LocalDataFlow.cs:337:13:337:52 | SSA def(taintedDataContract) | -| LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | LocalDataFlow.cs:339:15:339:20 | access to local variable sink53 | -| LocalDataFlow.cs:338:22:338:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:338:22:338:48 | access to property AString | -| LocalDataFlow.cs:338:22:338:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | -| LocalDataFlow.cs:338:22:338:48 | access to property AString | LocalDataFlow.cs:338:13:338:48 | SSA def(sink53) | -| LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | LocalDataFlow.cs:341:15:341:20 | access to local variable sink54 | -| LocalDataFlow.cs:340:22:340:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:340:22:340:46 | access to property AList | -| LocalDataFlow.cs:340:22:340:40 | access to local variable taintedDataContract | LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:340:22:340:46 | [post] access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:340:22:340:49 | access to indexer | -| LocalDataFlow.cs:340:22:340:46 | access to property AList | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:340:22:340:49 | access to indexer | LocalDataFlow.cs:340:22:340:57 | access to property AString | -| LocalDataFlow.cs:340:22:340:57 | access to property AString | LocalDataFlow.cs:340:13:340:57 | SSA def(sink54) | -| LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | -| LocalDataFlow.cs:344:38:344:55 | object creation of type DataContract | LocalDataFlow.cs:344:13:344:55 | SSA def(nonTaintedDataContract) | -| LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | LocalDataFlow.cs:346:15:346:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:345:20:345:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:345:20:345:49 | access to property AString | -| LocalDataFlow.cs:345:20:345:49 | access to property AString | LocalDataFlow.cs:345:9:345:49 | SSA def(nonSink0) | -| LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | LocalDataFlow.cs:348:15:348:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:347:20:347:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | -| LocalDataFlow.cs:347:20:347:44 | access to property AnInt | LocalDataFlow.cs:347:9:347:44 | SSA def(nonSink2) | -| LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | LocalDataFlow.cs:350:15:350:22 | access to local variable nonSink2 | -| LocalDataFlow.cs:349:20:349:38 | access to local variable taintedDataContract | LocalDataFlow.cs:349:20:349:44 | access to property AList | -| LocalDataFlow.cs:349:20:349:44 | access to property AList | LocalDataFlow.cs:349:20:349:47 | access to indexer | -| LocalDataFlow.cs:349:20:349:53 | access to property AnInt | LocalDataFlow.cs:349:9:349:53 | SSA def(nonSink2) | -| LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | -| LocalDataFlow.cs:353:34:353:37 | null | LocalDataFlow.cs:353:17:353:37 | SSA def(taintedTextBox) | -| LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | LocalDataFlow.cs:355:15:355:20 | access to local variable sink60 | -| LocalDataFlow.cs:354:22:354:35 | access to local variable taintedTextBox | LocalDataFlow.cs:354:22:354:40 | access to property Text | -| LocalDataFlow.cs:354:22:354:40 | access to property Text | LocalDataFlow.cs:354:13:354:40 | SSA def(sink60) | -| LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | -| LocalDataFlow.cs:358:37:358:40 | null | LocalDataFlow.cs:358:17:358:40 | SSA def(nonTaintedTextBox) | -| LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | LocalDataFlow.cs:360:15:360:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:359:20:359:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:359:20:359:41 | access to property Text | -| LocalDataFlow.cs:359:20:359:41 | access to property Text | LocalDataFlow.cs:359:9:359:41 | SSA def(nonSink0) | -| LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | LocalDataFlow.cs:364:19:364:24 | access to local variable sink61 | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:363:22:363:27 | SSA def(sink61) | -| LocalDataFlow.cs:363:32:363:37 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | -| LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | -| LocalDataFlow.cs:365:30:365:35 | access to local variable sink10 | LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | -| LocalDataFlow.cs:365:30:365:51 | call to method GetEnumerator | LocalDataFlow.cs:365:21:365:51 | SSA def(sink62) | -| LocalDataFlow.cs:366:15:366:20 | [post] access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:366:15:366:20 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | -| LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | LocalDataFlow.cs:368:15:368:20 | access to local variable sink63 | -| LocalDataFlow.cs:367:22:367:27 | access to local variable sink62 | LocalDataFlow.cs:367:22:367:35 | access to property Current | -| LocalDataFlow.cs:367:22:367:35 | access to property Current | LocalDataFlow.cs:367:13:367:35 | SSA def(sink63) | -| LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | -| LocalDataFlow.cs:369:57:369:61 | access to local variable sink3 | LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | -| LocalDataFlow.cs:369:57:369:77 | (...) ... | LocalDataFlow.cs:369:48:369:77 | SSA def(sink64) | -| LocalDataFlow.cs:369:57:369:77 | call to method GetEnumerator | LocalDataFlow.cs:369:57:369:77 | (...) ... | -| LocalDataFlow.cs:370:15:370:20 | [post] access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:370:15:370:20 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | -| LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | -| LocalDataFlow.cs:371:22:371:27 | access to local variable sink64 | LocalDataFlow.cs:371:22:371:35 | access to property Current | -| LocalDataFlow.cs:371:22:371:35 | access to property Current | LocalDataFlow.cs:371:13:371:35 | SSA def(sink65) | -| LocalDataFlow.cs:372:15:372:20 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | -| LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | LocalDataFlow.cs:374:15:374:20 | access to local variable sink66 | -| LocalDataFlow.cs:373:22:373:27 | access to local variable sink65 | LocalDataFlow.cs:373:22:373:33 | access to property Value | -| LocalDataFlow.cs:373:22:373:33 | access to property Value | LocalDataFlow.cs:373:13:373:33 | SSA def(sink66) | -| LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | LocalDataFlow.cs:378:19:378:27 | access to local variable nonSink17 | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:377:22:377:30 | SSA def(nonSink17) | -| LocalDataFlow.cs:377:35:377:42 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | -| LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | -| LocalDataFlow.cs:379:33:379:40 | access to local variable nonSink4 | LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | -| LocalDataFlow.cs:379:33:379:56 | call to method GetEnumerator | LocalDataFlow.cs:379:21:379:56 | SSA def(nonSink18) | -| LocalDataFlow.cs:380:15:380:23 | [post] access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:380:15:380:23 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | -| LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | LocalDataFlow.cs:382:15:382:22 | access to local variable nonSink3 | -| LocalDataFlow.cs:381:20:381:28 | access to local variable nonSink18 | LocalDataFlow.cs:381:20:381:36 | access to property Current | -| LocalDataFlow.cs:381:20:381:36 | access to property Current | LocalDataFlow.cs:381:9:381:36 | SSA def(nonSink3) | -| LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | -| LocalDataFlow.cs:383:63:383:70 | access to local variable nonSink1 | LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | -| LocalDataFlow.cs:383:63:383:86 | (...) ... | LocalDataFlow.cs:383:51:383:86 | SSA def(nonSink19) | -| LocalDataFlow.cs:383:63:383:86 | call to method GetEnumerator | LocalDataFlow.cs:383:63:383:86 | (...) ... | -| LocalDataFlow.cs:384:15:384:23 | [post] access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:384:15:384:23 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | -| LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | -| LocalDataFlow.cs:385:25:385:33 | access to local variable nonSink19 | LocalDataFlow.cs:385:25:385:41 | access to property Current | -| LocalDataFlow.cs:385:25:385:41 | access to property Current | LocalDataFlow.cs:385:13:385:41 | SSA def(nonSink20) | -| LocalDataFlow.cs:386:15:386:23 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | -| LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | LocalDataFlow.cs:388:15:388:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:387:20:387:28 | access to local variable nonSink20 | LocalDataFlow.cs:387:20:387:34 | access to property Value | -| LocalDataFlow.cs:387:20:387:34 | access to property Value | LocalDataFlow.cs:387:9:387:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | -| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | -| LocalDataFlow.cs:391:31:391:50 | [output] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run | -| LocalDataFlow.cs:392:15:392:20 | [post] access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | -| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 | -| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | -| LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 | LocalDataFlow.cs:393:22:393:33 | await ... | -| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | -| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | -| LocalDataFlow.cs:397:34:397:41 | [output] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run | -| LocalDataFlow.cs:398:15:398:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | -| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | -| LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 | LocalDataFlow.cs:399:20:399:34 | await ... | -| LocalDataFlow.cs:400:15:400:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 | LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | -| LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | LocalDataFlow.cs:404:15:404:20 | access to local variable sink69 | -| LocalDataFlow.cs:403:22:403:36 | $"..." | LocalDataFlow.cs:403:13:403:36 | SSA def(sink69) | -| LocalDataFlow.cs:403:24:403:28 | "test " | LocalDataFlow.cs:403:22:403:36 | $"..." | -| LocalDataFlow.cs:403:30:403:34 | access to local variable sink1 | LocalDataFlow.cs:403:22:403:36 | $"..." | -| LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:407:20:407:37 | $"..." | LocalDataFlow.cs:407:9:407:37 | SSA def(nonSink0) | -| LocalDataFlow.cs:407:22:407:26 | "test " | LocalDataFlow.cs:407:20:407:37 | $"..." | -| LocalDataFlow.cs:407:28:407:35 | access to local variable nonSink0 | LocalDataFlow.cs:407:20:407:37 | $"..." | -| LocalDataFlow.cs:408:15:408:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:408:15:408:22 | access to local variable nonSink0 | LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | -| LocalDataFlow.cs:411:22:411:34 | ... = ... | LocalDataFlow.cs:411:13:411:34 | SSA def(sink70) | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | -| LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | ... = ... | -| LocalDataFlow.cs:411:30:411:34 | access to local variable sink0 | LocalDataFlow.cs:411:22:411:34 | SSA def(sink0) | -| LocalDataFlow.cs:412:15:412:20 | [post] access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:412:15:412:20 | access to local variable sink70 | LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | -| LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | -| LocalDataFlow.cs:415:20:415:38 | ... = ... | LocalDataFlow.cs:415:9:415:38 | SSA def(nonSink0) | -| LocalDataFlow.cs:415:31:415:38 | access to local variable nonSink0 | LocalDataFlow.cs:415:20:415:38 | ... = ... | -| LocalDataFlow.cs:416:15:416:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:416:15:416:22 | access to local variable nonSink0 | LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | -| LocalDataFlow.cs:419:13:419:18 | access to local variable sink70 | LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | -| LocalDataFlow.cs:419:23:419:35 | SSA def(sink71) | LocalDataFlow.cs:420:19:420:24 | access to local variable sink71 | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | -| LocalDataFlow.cs:423:13:423:20 | access to local variable nonSink0 | LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | -| LocalDataFlow.cs:423:25:423:40 | SSA def(nonSink16) | LocalDataFlow.cs:424:19:424:27 | access to local variable nonSink16 | -| LocalDataFlow.cs:427:17:427:22 | access to local variable sink70 | LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | -| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | -| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | -| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 | -| LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | LocalDataFlow.cs:445:15:445:20 | access to local variable sink73 | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:22:443:29 | access to local variable nonSink0 | LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | -| LocalDataFlow.cs:443:22:443:38 | ... ?? ... | LocalDataFlow.cs:443:13:443:38 | SSA def(sink73) | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:443:22:443:38 | ... ?? ... | -| LocalDataFlow.cs:443:34:443:38 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | -| LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | LocalDataFlow.cs:446:15:446:20 | access to local variable sink74 | -| LocalDataFlow.cs:444:22:444:26 | access to local variable sink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:444:22:444:38 | ... ?? ... | LocalDataFlow.cs:444:13:444:38 | SSA def(sink74) | -| LocalDataFlow.cs:444:31:444:38 | access to local variable nonSink0 | LocalDataFlow.cs:444:22:444:38 | ... ?? ... | -| LocalDataFlow.cs:464:28:464:30 | this | LocalDataFlow.cs:464:41:464:45 | this access | -| LocalDataFlow.cs:464:50:464:52 | this | LocalDataFlow.cs:464:56:464:60 | this access | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:50:464:52 | value | -| LocalDataFlow.cs:464:50:464:52 | value | LocalDataFlow.cs:464:64:464:68 | access to parameter value | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:470:41:470:47 | tainted | -| LocalDataFlow.cs:470:41:470:47 | tainted | LocalDataFlow.cs:472:15:472:21 | access to parameter tainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:475:44:475:53 | nonTainted | -| LocalDataFlow.cs:475:44:475:53 | nonTainted | LocalDataFlow.cs:477:15:477:24 | access to parameter nonTainted | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:480:44:480:44 | x | -| LocalDataFlow.cs:480:44:480:44 | x | LocalDataFlow.cs:483:21:483:21 | access to parameter x | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:480:67:480:68 | os | -| LocalDataFlow.cs:480:67:480:68 | os | LocalDataFlow.cs:486:32:486:33 | access to parameter os | -| LocalDataFlow.cs:483:21:483:21 | access to parameter x | LocalDataFlow.cs:483:16:483:21 | ... = ... | -| LocalDataFlow.cs:486:32:486:33 | access to parameter os | LocalDataFlow.cs:486:26:486:33 | ... = ... | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:491:41:491:44 | args | -| LocalDataFlow.cs:491:41:491:44 | args | LocalDataFlow.cs:493:29:493:32 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | [post] access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:493:29:493:32 | call to operator implicit conversion | -| LocalDataFlow.cs:493:29:493:32 | access to parameter args | LocalDataFlow.cs:494:27:494:30 | access to parameter args | +| LocalDataFlow.cs:66:15:66:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:66:15:66:22 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:69:21:69:32 | ... + ... | +| LocalDataFlow.cs:69:21:69:25 | access to local variable sink1 | LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | +| LocalDataFlow.cs:69:21:69:32 | ... + ... | LocalDataFlow.cs:69:13:69:32 | SSA def(sink5) | +| LocalDataFlow.cs:69:29:69:32 | "ok" | LocalDataFlow.cs:69:21:69:32 | ... + ... | +| LocalDataFlow.cs:70:15:70:19 | [post] access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:70:15:70:19 | access to local variable sink5 | LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | +| LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:73:20:73:27 | access to local variable nonSink0 | LocalDataFlow.cs:73:20:73:36 | ... + ... | +| LocalDataFlow.cs:73:20:73:36 | ... + ... | LocalDataFlow.cs:73:9:73:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:73:31:73:36 | "test" | LocalDataFlow.cs:73:20:73:36 | ... + ... | +| LocalDataFlow.cs:74:15:74:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:74:15:74:22 | access to local variable nonSink0 | LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | +| LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | +| LocalDataFlow.cs:77:22:77:26 | access to local variable sink5 | LocalDataFlow.cs:77:13:77:27 | SSA def(sink6) | +| LocalDataFlow.cs:78:15:78:19 | [post] access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:78:15:78:19 | access to local variable sink6 | LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | +| LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | LocalDataFlow.cs:82:15:82:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:81:21:81:28 | access to local variable nonSink0 | LocalDataFlow.cs:81:9:81:29 | SSA def(nonSink0) | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | +| LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): false] access to parameter b | +| LocalDataFlow.cs:85:21:85:21 | access to parameter b | LocalDataFlow.cs:89:20:89:20 | [b (line 49): true] access to parameter b | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): false] SSA def(sink7) | +| LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | LocalDataFlow.cs:85:13:85:35 | [b (line 49): true] SSA def(sink7) | +| LocalDataFlow.cs:85:25:85:27 | [b (line 49): true] "a" | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:85:31:85:35 | [b (line 49): false] access to local variable sink6 | LocalDataFlow.cs:85:21:85:35 | ... ? ... : ... | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): false] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:86:15:86:19 | [b (line 49): true] access to local variable sink7 | LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | +| LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:89:9:89:36 | SSA phi(sink7) | LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | LocalDataFlow.cs:89:9:89:36 | SSA def(nonSink0) | +| LocalDataFlow.cs:89:24:89:28 | "abc" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): true] ... ? ... : ... | +| LocalDataFlow.cs:89:32:89:36 | "def" | LocalDataFlow.cs:89:20:89:36 | [b (line 49): false] ... ? ... : ... | +| LocalDataFlow.cs:90:15:90:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:90:15:90:22 | access to local variable nonSink0 | LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | +| LocalDataFlow.cs:93:21:93:33 | (...) ... | LocalDataFlow.cs:93:13:93:33 | SSA def(sink8) | +| LocalDataFlow.cs:93:29:93:33 | access to local variable sink7 | LocalDataFlow.cs:93:21:93:33 | (...) ... | +| LocalDataFlow.cs:94:15:94:19 | [post] access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:94:15:94:19 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | +| LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | LocalDataFlow.cs:98:15:98:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:97:24:97:39 | (...) ... | LocalDataFlow.cs:97:13:97:39 | SSA def(nonSink3) | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:97:24:97:39 | (...) ... | +| LocalDataFlow.cs:97:32:97:39 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:101:21:101:35 | ... as ... | +| LocalDataFlow.cs:101:21:101:25 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | +| LocalDataFlow.cs:101:21:101:35 | ... as ... | LocalDataFlow.cs:101:13:101:35 | SSA def(sink9) | +| LocalDataFlow.cs:102:15:102:19 | [post] access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:102:15:102:19 | access to local variable sink9 | LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | +| LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:105:20:105:37 | ... as ... | +| LocalDataFlow.cs:105:20:105:27 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:105:20:105:37 | ... as ... | LocalDataFlow.cs:105:9:105:37 | SSA def(nonSink3) | +| LocalDataFlow.cs:106:15:106:22 | [post] access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 | +| LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | +| LocalDataFlow.cs:109:22:109:39 | call to method Parse | LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | +| LocalDataFlow.cs:109:34:109:38 | [post] access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:109:22:109:39 | call to method Parse | +| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | +| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | +| LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 | +| LocalDataFlow.cs:112:22:112:56 | call to method TryParse | LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | +| LocalDataFlow.cs:112:37:112:41 | [post] access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:112:22:112:56 | call to method TryParse | +| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | +| LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 | +| LocalDataFlow.cs:114:22:114:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:49 | call to method Replace | +| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | +| LocalDataFlow.cs:114:22:114:49 | call to method Replace | LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | +| LocalDataFlow.cs:114:44:114:48 | [post] access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:114:22:114:49 | call to method Replace | +| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | +| LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | +| LocalDataFlow.cs:116:22:116:51 | call to method Format | LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | +| LocalDataFlow.cs:116:36:116:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:116:22:116:51 | call to method Format | +| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:116:46:116:50 | [post] access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:116:22:116:51 | call to method Format | +| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | +| LocalDataFlow.cs:117:15:117:20 | [post] access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | +| LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 | +| LocalDataFlow.cs:118:22:118:52 | call to method Format | LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | +| LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | LocalDataFlow.cs:118:22:118:52 | call to method Format | +| LocalDataFlow.cs:118:44:118:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:118:22:118:52 | call to method Format | +| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 | +| LocalDataFlow.cs:120:22:120:38 | call to method Parse | LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | +| LocalDataFlow.cs:120:33:120:37 | [post] access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:38 | call to method Parse | +| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | +| LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | +| LocalDataFlow.cs:123:22:123:56 | call to method TryParse | LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | +| LocalDataFlow.cs:123:36:123:40 | [post] access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:123:22:123:56 | call to method TryParse | +| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | +| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | +| LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | +| LocalDataFlow.cs:125:22:125:43 | call to method ToByte | LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | +| LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | LocalDataFlow.cs:125:22:125:43 | call to method ToByte | +| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | +| LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | +| LocalDataFlow.cs:127:22:127:46 | call to method Concat | LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | +| LocalDataFlow.cs:127:36:127:37 | "" | LocalDataFlow.cs:127:22:127:46 | call to method Concat | +| LocalDataFlow.cs:127:40:127:45 | (...) ... | LocalDataFlow.cs:127:22:127:46 | call to method Concat | +| LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | (...) ... | +| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | +| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | +| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | +| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy | +| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | +| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | +| LocalDataFlow.cs:131:22:131:54 | call to method Join | LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | +| LocalDataFlow.cs:131:34:131:37 | ", " | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:40:131:41 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:131:52:131:53 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join | +| LocalDataFlow.cs:132:15:132:20 | [post] access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | +| LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 | +| LocalDataFlow.cs:133:22:133:23 | "" | LocalDataFlow.cs:133:22:133:41 | call to method Insert | +| LocalDataFlow.cs:133:22:133:41 | call to method Insert | LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | +| LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | LocalDataFlow.cs:133:22:133:41 | call to method Insert | +| LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | LocalDataFlow.cs:138:15:138:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:137:20:137:40 | call to method Parse | LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | +| LocalDataFlow.cs:137:32:137:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:137:20:137:40 | call to method Parse | +| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | LocalDataFlow.cs:140:15:140:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:139:24:139:61 | call to method TryParse | LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | +| LocalDataFlow.cs:139:39:139:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:139:24:139:61 | call to method TryParse | +| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace | +| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:141:20:141:50 | call to method Replace | LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | +| LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace | +| LocalDataFlow.cs:142:15:142:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:20:143:52 | call to method Format | LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | +| LocalDataFlow.cs:143:34:143:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format | +| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | +| LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format | +| LocalDataFlow.cs:144:15:144:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | LocalDataFlow.cs:146:15:146:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:145:20:145:39 | call to method Parse | LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | +| LocalDataFlow.cs:145:31:145:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:145:20:145:39 | call to method Parse | +| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | +| LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:147:20:147:57 | call to method TryParse | LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | +| LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | LocalDataFlow.cs:147:20:147:57 | call to method TryParse | +| LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | +| LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | LocalDataFlow.cs:150:15:150:23 | access to local variable nonSink14 | +| LocalDataFlow.cs:149:25:149:48 | call to method ToByte | LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:149:25:149:48 | call to method ToByte | +| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | +| LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:151:20:151:46 | call to method Concat | LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | +| LocalDataFlow.cs:151:34:151:35 | "" | LocalDataFlow.cs:151:20:151:46 | call to method Concat | +| LocalDataFlow.cs:151:38:151:45 | (...) ... | LocalDataFlow.cs:151:20:151:46 | call to method Concat | +| LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | (...) ... | +| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy | +| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:155:20:155:54 | call to method Join | LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | +| LocalDataFlow.cs:155:32:155:35 | ", " | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:38:155:39 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:155:52:155:53 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join | +| LocalDataFlow.cs:156:15:156:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:157:20:157:21 | "" | LocalDataFlow.cs:157:20:157:41 | call to method Insert | +| LocalDataFlow.cs:157:20:157:41 | call to method Insert | LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | LocalDataFlow.cs:157:20:157:41 | call to method Insert | +| LocalDataFlow.cs:158:15:158:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | +| LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | +| LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:32 | ... > ... | +| LocalDataFlow.cs:161:22:161:32 | ... > ... | LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | +| LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | +| LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | LocalDataFlow.cs:164:15:164:20 | access to local variable sink21 | +| LocalDataFlow.cs:163:22:163:26 | [post] access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:40 | call to method Equals | +| LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 | LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | +| LocalDataFlow.cs:163:22:163:40 | call to method Equals | LocalDataFlow.cs:163:13:163:40 | SSA def(sink21) | +| LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | LocalDataFlow.cs:166:15:166:20 | access to local variable sink22 | +| LocalDataFlow.cs:165:22:165:26 | [post] access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:165:22:165:45 | call to method Equals | +| LocalDataFlow.cs:165:22:165:26 | access to local variable sink8 | LocalDataFlow.cs:171:20:171:24 | access to local variable sink8 | +| LocalDataFlow.cs:165:22:165:45 | call to method Equals | LocalDataFlow.cs:165:13:165:45 | SSA def(sink22) | +| LocalDataFlow.cs:165:43:165:44 | 41 | LocalDataFlow.cs:165:35:165:44 | (...) ... | +| LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | LocalDataFlow.cs:170:15:170:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:169:20:169:24 | [post] access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:24 | access to local variable sink0 | LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | +| LocalDataFlow.cs:169:20:169:38 | call to method Equals | LocalDataFlow.cs:169:9:169:38 | SSA def(nonSink7) | +| LocalDataFlow.cs:169:33:169:37 | [post] access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:169:33:169:37 | access to local variable sink1 | LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | +| LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:171:20:171:41 | call to method Equals | LocalDataFlow.cs:171:9:171:41 | SSA def(nonSink7) | +| LocalDataFlow.cs:172:15:172:22 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | +| LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | LocalDataFlow.cs:176:15:176:20 | access to local variable sink25 | +| LocalDataFlow.cs:175:22:175:27 | access to local variable sink20 | LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | +| LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | LocalDataFlow.cs:175:13:175:36 | SSA def(sink25) | +| LocalDataFlow.cs:175:32:175:36 | false | LocalDataFlow.cs:175:22:175:36 | ... \|\| ... | +| LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | LocalDataFlow.cs:180:15:180:22 | access to local variable nonSink7 | +| LocalDataFlow.cs:179:20:179:27 | access to local variable nonSink7 | LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | +| LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) | +| LocalDataFlow.cs:179:32:179:36 | false | LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | +| LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | +| LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | +| LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | +| LocalDataFlow.cs:184:15:184:20 | [post] access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 | +| LocalDataFlow.cs:185:22:185:27 | [post] access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:38 | call to method ToString | +| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | +| LocalDataFlow.cs:185:22:185:38 | call to method ToString | LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | +| LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 | +| LocalDataFlow.cs:187:22:187:27 | [post] access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | +| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | +| LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | +| LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 | +| LocalDataFlow.cs:189:22:189:27 | [post] access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:33 | access to property Query | +| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | +| LocalDataFlow.cs:189:22:189:33 | access to property Query | LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | +| LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | +| LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | +| LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | +| LocalDataFlow.cs:192:15:192:20 | [post] access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | +| LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | +| LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | +| LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | +| LocalDataFlow.cs:196:15:196:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | LocalDataFlow.cs:198:15:198:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:197:20:197:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:38 | call to method ToString | +| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:197:20:197:38 | call to method ToString | LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | LocalDataFlow.cs:200:15:200:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:199:20:199:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | +| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | +| LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | LocalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:201:20:201:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:33 | access to property Query | +| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | +| LocalDataFlow.cs:201:20:201:33 | access to property Query | LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | +| LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | +| LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | +| LocalDataFlow.cs:204:15:204:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | +| LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | +| LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | +| LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | +| LocalDataFlow.cs:208:15:208:20 | [post] access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | +| LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | +| LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | +| LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | +| LocalDataFlow.cs:210:15:210:20 | [post] access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | +| LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | +| LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | +| LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | +| LocalDataFlow.cs:214:15:214:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | +| LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | +| LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:216:15:216:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | +| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | +| LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:48 | call to method Substring | +| LocalDataFlow.cs:219:30:219:48 | call to method Substring | LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | +| LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | +| LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | LocalDataFlow.cs:219:30:219:87 | call to method Trim | +| LocalDataFlow.cs:219:30:219:87 | call to method Trim | LocalDataFlow.cs:219:30:219:105 | call to method Replace | +| LocalDataFlow.cs:219:30:219:105 | call to method Replace | LocalDataFlow.cs:219:30:219:119 | call to method Insert | +| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone | +| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... | +| LocalDataFlow.cs:219:102:219:104 | "b" | LocalDataFlow.cs:219:30:219:105 | call to method Replace | +| LocalDataFlow.cs:219:117:219:118 | "" | LocalDataFlow.cs:219:30:219:119 | call to method Insert | +| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | +| LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 | +| LocalDataFlow.cs:221:22:221:27 | [post] access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:39 | call to method Normalize | +| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | +| LocalDataFlow.cs:221:22:221:39 | call to method Normalize | LocalDataFlow.cs:221:22:221:52 | call to method Remove | +| LocalDataFlow.cs:221:22:221:52 | call to method Remove | LocalDataFlow.cs:221:22:221:63 | call to method Split | +| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | +| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | +| LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:48 | call to method Substring | +| LocalDataFlow.cs:225:28:225:48 | call to method Substring | LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | +| LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | +| LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | LocalDataFlow.cs:225:28:225:87 | call to method Trim | +| LocalDataFlow.cs:225:28:225:87 | call to method Trim | LocalDataFlow.cs:225:28:225:105 | call to method Replace | +| LocalDataFlow.cs:225:28:225:105 | call to method Replace | LocalDataFlow.cs:225:28:225:119 | call to method Insert | +| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone | +| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... | +| LocalDataFlow.cs:225:102:225:104 | "b" | LocalDataFlow.cs:225:28:225:105 | call to method Replace | +| LocalDataFlow.cs:225:117:225:118 | "" | LocalDataFlow.cs:225:28:225:119 | call to method Insert | +| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | LocalDataFlow.cs:228:15:228:23 | access to local variable nonSink15 | +| LocalDataFlow.cs:227:25:227:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:44 | call to method Normalize | +| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | +| LocalDataFlow.cs:227:25:227:44 | call to method Normalize | LocalDataFlow.cs:227:25:227:57 | call to method Remove | +| LocalDataFlow.cs:227:25:227:57 | call to method Remove | LocalDataFlow.cs:227:25:227:68 | call to method Split | +| LocalDataFlow.cs:227:25:227:68 | call to method Split | LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | +| LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | +| LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | +| LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | +| LocalDataFlow.cs:232:15:232:20 | [post] access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | +| LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | +| LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:38 | call to method ToString | +| LocalDataFlow.cs:233:22:233:38 | call to method ToString | LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | +| LocalDataFlow.cs:234:15:234:20 | [post] access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | +| LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | +| LocalDataFlow.cs:235:40:235:41 | "" | LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | +| LocalDataFlow.cs:236:9:236:14 | [post] access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 | +| LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | +| LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | +| LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | +| LocalDataFlow.cs:241:15:241:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:242:20:242:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:39 | call to method ToString | +| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:242:20:242:39 | call to method ToString | LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | +| LocalDataFlow.cs:243:15:243:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | +| LocalDataFlow.cs:244:9:244:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 | +| LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | +| LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:248:13:248:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:248:35:248:52 | object creation of type DataContract | LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | +| LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 | +| LocalDataFlow.cs:249:22:249:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:249:22:249:48 | access to property AString | +| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | +| LocalDataFlow.cs:249:22:249:48 | access to property AString | LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | +| LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 | +| LocalDataFlow.cs:251:22:251:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:46 | access to property AList | +| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:251:22:251:46 | [post] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:251:22:251:49 | access to indexer | +| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:251:22:251:49 | access to indexer | LocalDataFlow.cs:251:22:251:57 | access to property AString | +| LocalDataFlow.cs:251:22:251:57 | access to property AString | LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | +| LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | +| LocalDataFlow.cs:255:38:255:55 | object creation of type DataContract | LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | +| LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | LocalDataFlow.cs:257:15:257:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:256:20:256:49 | access to property AString | +| LocalDataFlow.cs:256:20:256:49 | access to property AString | LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | +| LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | LocalDataFlow.cs:259:15:259:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:258:20:258:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | +| LocalDataFlow.cs:258:20:258:44 | access to property AnInt | LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | +| LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | LocalDataFlow.cs:261:15:261:22 | access to local variable nonSink2 | +| LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:44 | access to property AList | +| LocalDataFlow.cs:260:20:260:44 | access to property AList | LocalDataFlow.cs:260:20:260:47 | access to indexer | +| LocalDataFlow.cs:260:20:260:53 | access to property AnInt | LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | +| LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | +| LocalDataFlow.cs:264:34:264:37 | null | LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | +| LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 | +| LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | LocalDataFlow.cs:265:22:265:40 | access to property Text | +| LocalDataFlow.cs:265:22:265:40 | access to property Text | LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | +| LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | +| LocalDataFlow.cs:269:37:269:40 | null | LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | +| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:270:20:270:41 | access to property Text | +| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | +| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | +| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | +| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run | +| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | +| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 | +| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | +| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... | +| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | +| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | +| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run | +| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | +| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:282:20:282:34 | await ... | LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | +| LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 | LocalDataFlow.cs:282:20:282:34 | await ... | +| LocalDataFlow.cs:283:15:283:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 | LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | +| LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | LocalDataFlow.cs:287:15:287:20 | access to local variable sink69 | +| LocalDataFlow.cs:286:22:286:36 | $"..." | LocalDataFlow.cs:286:13:286:36 | SSA def(sink69) | +| LocalDataFlow.cs:286:24:286:28 | "test " | LocalDataFlow.cs:286:22:286:36 | $"..." | +| LocalDataFlow.cs:286:30:286:34 | access to local variable sink1 | LocalDataFlow.cs:286:22:286:36 | $"..." | +| LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:290:20:290:37 | $"..." | LocalDataFlow.cs:290:9:290:37 | SSA def(nonSink0) | +| LocalDataFlow.cs:290:22:290:26 | "test " | LocalDataFlow.cs:290:20:290:37 | $"..." | +| LocalDataFlow.cs:290:28:290:35 | access to local variable nonSink0 | LocalDataFlow.cs:290:20:290:37 | $"..." | +| LocalDataFlow.cs:291:15:291:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:291:15:291:22 | access to local variable nonSink0 | LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | +| LocalDataFlow.cs:294:22:294:34 | ... = ... | LocalDataFlow.cs:294:13:294:34 | SSA def(sink70) | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | +| LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | ... = ... | +| LocalDataFlow.cs:294:30:294:34 | access to local variable sink0 | LocalDataFlow.cs:294:22:294:34 | SSA def(sink0) | +| LocalDataFlow.cs:295:15:295:20 | [post] access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:295:15:295:20 | access to local variable sink70 | LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | +| LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | +| LocalDataFlow.cs:298:20:298:38 | ... = ... | LocalDataFlow.cs:298:9:298:38 | SSA def(nonSink0) | +| LocalDataFlow.cs:298:31:298:38 | access to local variable nonSink0 | LocalDataFlow.cs:298:20:298:38 | ... = ... | +| LocalDataFlow.cs:299:15:299:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:299:15:299:22 | access to local variable nonSink0 | LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | +| LocalDataFlow.cs:302:13:302:18 | access to local variable sink70 | LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | +| LocalDataFlow.cs:302:23:302:35 | SSA def(sink71) | LocalDataFlow.cs:303:19:303:24 | access to local variable sink71 | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | +| LocalDataFlow.cs:306:13:306:20 | access to local variable nonSink0 | LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | +| LocalDataFlow.cs:306:25:306:40 | SSA def(nonSink16) | LocalDataFlow.cs:307:19:307:27 | access to local variable nonSink16 | +| LocalDataFlow.cs:310:17:310:22 | access to local variable sink70 | LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | +| LocalDataFlow.cs:312:18:312:30 | SSA def(sink72) | LocalDataFlow.cs:313:23:313:28 | access to local variable sink72 | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | +| LocalDataFlow.cs:318:17:318:24 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | +| LocalDataFlow.cs:320:18:320:33 | SSA def(nonSink17) | LocalDataFlow.cs:321:23:321:31 | access to local variable nonSink17 | +| LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | LocalDataFlow.cs:328:15:328:20 | access to local variable sink73 | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:22:326:29 | access to local variable nonSink0 | LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | +| LocalDataFlow.cs:326:22:326:38 | ... ?? ... | LocalDataFlow.cs:326:13:326:38 | SSA def(sink73) | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:326:22:326:38 | ... ?? ... | +| LocalDataFlow.cs:326:34:326:38 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | +| LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | LocalDataFlow.cs:329:15:329:20 | access to local variable sink74 | +| LocalDataFlow.cs:327:22:327:26 | access to local variable sink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:327:22:327:38 | ... ?? ... | LocalDataFlow.cs:327:13:327:38 | SSA def(sink74) | +| LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... | +| LocalDataFlow.cs:347:28:347:30 | this | LocalDataFlow.cs:347:41:347:45 | this access | +| LocalDataFlow.cs:347:50:347:52 | this | LocalDataFlow.cs:347:56:347:60 | this access | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:50:347:52 | value | +| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:64:347:68 | access to parameter value | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:353:41:353:47 | tainted | +| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:355:15:355:21 | access to parameter tainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:358:44:358:53 | nonTainted | +| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:360:15:360:24 | access to parameter nonTainted | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:363:44:363:44 | x | +| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:366:21:366:21 | access to parameter x | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:363:67:363:68 | os | +| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:369:32:369:33 | access to parameter os | +| LocalDataFlow.cs:366:21:366:21 | access to parameter x | LocalDataFlow.cs:366:16:366:21 | ... = ... | +| LocalDataFlow.cs:369:32:369:33 | access to parameter os | LocalDataFlow.cs:369:26:369:33 | ... = ... | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:374:41:374:44 | args | +| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:376:29:376:32 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | [post] access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:376:29:376:32 | call to operator implicit conversion | +| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args | | SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S | | SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access | | SSA.cs:5:26:5:32 | tainted | SSA.cs:5:26:5:32 | tainted | diff --git a/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected b/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected index c5a0b98598f..61bc9b2261c 100644 --- a/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected +++ b/csharp/ql/test/library-tests/ir/ir/raw_ir_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index c5a0b98598f..61bc9b2261c 100644 --- a/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/csharp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -9,6 +9,7 @@ instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction +memoryOperandDefinitionIsUnmodeled operandAcrossFunctions instructionWithoutUniqueBlock containsLoopOfForwardEdges diff --git a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected index 06473196df9..a9eb533c152 100644 --- a/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected +++ b/csharp/ql/test/library-tests/standalone/controlflow/cfg.expected @@ -7,9 +7,14 @@ | ControlFlow.cs:10:9:10:43 | Call (unknown target) | ControlFlow.cs:12:9:12:87 | ...; | | ControlFlow.cs:10:9:10:43 | call to method | ControlFlow.cs:12:9:12:87 | ...; | | ControlFlow.cs:10:9:10:44 | ...; | ControlFlow.cs:10:9:10:13 | Expression | -| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Expression | -| ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression | -| ControlFlow.cs:10:22:10:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" | +| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Call (unknown target) | +| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | access to property (unknown) | +| ControlFlow.cs:10:22:10:24 | Call (unknown target) | ControlFlow.cs:10:22:10:26 | Call (unknown target) | +| ControlFlow.cs:10:22:10:24 | Call (unknown target) | ControlFlow.cs:10:22:10:26 | access to property (unknown) | +| ControlFlow.cs:10:22:10:24 | access to property (unknown) | ControlFlow.cs:10:22:10:26 | Call (unknown target) | +| ControlFlow.cs:10:22:10:24 | access to property (unknown) | ControlFlow.cs:10:22:10:26 | access to property (unknown) | +| ControlFlow.cs:10:22:10:26 | Call (unknown target) | ControlFlow.cs:10:29:10:42 | "This is true" | +| ControlFlow.cs:10:22:10:26 | access to property (unknown) | ControlFlow.cs:10:29:10:42 | "This is true" | | ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | Call (unknown target) | | ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | call to method | | ControlFlow.cs:12:9:12:86 | Call (unknown target) | ControlFlow.cs:12:37:12:47 | Expression | @@ -20,5 +25,7 @@ | ControlFlow.cs:12:51:12:62 | access to field Empty | ControlFlow.cs:12:37:12:62 | ... = ... | | ControlFlow.cs:12:65:12:75 | Expression | ControlFlow.cs:12:79:12:79 | access to local variable v | | ControlFlow.cs:12:65:12:84 | ... = ... | ControlFlow.cs:12:35:12:86 | { ..., ... } | -| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Expression | -| ControlFlow.cs:12:79:12:84 | Expression | ControlFlow.cs:12:65:12:84 | ... = ... | +| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Call (unknown target) | +| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | access to property (unknown) | +| ControlFlow.cs:12:79:12:84 | Call (unknown target) | ControlFlow.cs:12:65:12:84 | ... = ... | +| ControlFlow.cs:12:79:12:84 | access to property (unknown) | ControlFlow.cs:12:65:12:84 | ... = ... | diff --git a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected index 05ae24318c3..d57c3c86bbd 100644 --- a/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected +++ b/csharp/ql/test/library-tests/standalone/errorrecovery/ErrorCalls.expected @@ -2,5 +2,5 @@ | errors.cs:43:21:43:28 | errors.cs:43:21:43:28 | object creation of type C1 | C1 | | errors.cs:44:13:44:19 | errors.cs:44:13:44:19 | call to method m1 | m1 | | errors.cs:45:13:45:19 | errors.cs:45:13:45:19 | call to method m2 | m2 | -| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | call to method | none | +| errors.cs:46:13:46:38 | errors.cs:46:13:46:38 | call to method WriteLine | WriteLine | | errors.cs:53:17:53:25 | errors.cs:53:17:53:25 | object creation of type C2 | none | diff --git a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected index 47045b907f6..2c8616d347a 100644 --- a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected +++ b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.expected @@ -1,2 +1,3 @@ -| regressions.cs:16:13:16:37 | case ...: | regressions.cs:16:18:16:36 | Expression | -| regressions.cs:18:13:18:37 | case ...: | regressions.cs:18:18:18:36 | Expression | +| regressions.cs:16:13:16:37 | case ...: | regressions.cs:16:18:16:36 | access to property (unknown) | +| regressions.cs:18:13:18:37 | case ...: | regressions.cs:18:18:18:36 | access to property (unknown) | +| regressions.cs:20:13:20:23 | case ...: | regressions.cs:20:18:20:22 | Int32 x | diff --git a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql index 7ee7754e91e..6c5d54518fe 100644 --- a/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql +++ b/csharp/ql/test/library-tests/standalone/regressions/ConstCase.ql @@ -1,7 +1,5 @@ import csharp from Case c, Expr e -where - e = c.getPattern().stripCasts() and - (e instanceof @unknown_expr or e instanceof ConstantPatternExpr) +where e = c.getPattern().stripCasts() select c, e diff --git a/csharp/ql/test/qlpack.yml b/csharp/ql/test/qlpack.yml index 20f6e83ee30..2b8cce91f07 100644 --- a/csharp/ql/test/qlpack.yml +++ b/csharp/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-csharp-tests version: 0.0.0 libraryPathDependencies: codeql-csharp +extractor: csharp diff --git a/csharp/ql/test/query-tests/Nullness/E.cs b/csharp/ql/test/query-tests/Nullness/E.cs index 0c020e9b150..67b5267ffbe 100644 --- a/csharp/ql/test/query-tests/Nullness/E.cs +++ b/csharp/ql/test/query-tests/Nullness/E.cs @@ -376,6 +376,15 @@ public class E } return -1; } + + static bool Ex37(E e1, E e2) + { + if ((e1 == null && e2 != null) || (e1 != null && e2 == null)) + return false; + if (e1 == null && e2 == null) + return true; + return e1.Long == e2.Long; // GOOD (false positive) + } } public static class Extensions diff --git a/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected b/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected index 2aa5b3f4f5e..5f739e93c2b 100644 --- a/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected +++ b/csharp/ql/test/query-tests/Nullness/EqualityCheck.expected @@ -220,6 +220,20 @@ | E.cs:355:13:355:21 | dynamic call to operator != | false | E.cs:355:18:355:21 | null | E.cs:355:13:355:13 | access to local variable x | | E.cs:362:13:362:29 | ... != ... | false | E.cs:362:13:362:13 | access to local variable x | E.cs:362:18:362:29 | (...) ... | | E.cs:362:13:362:29 | ... != ... | false | E.cs:362:18:362:29 | (...) ... | E.cs:362:13:362:13 | access to local variable x | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | E.cs:382:20:382:23 | null | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:20:382:23 | null | E.cs:382:14:382:15 | access to parameter e1 | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:34:382:37 | null | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:34:382:37 | null | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | E.cs:382:50:382:53 | null | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:50:382:53 | null | E.cs:382:44:382:45 | access to parameter e1 | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | E.cs:382:64:382:67 | null | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:64:382:67 | null | E.cs:382:58:382:59 | access to parameter e2 | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | E.cs:384:19:384:22 | null | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:19:384:22 | null | E.cs:384:13:384:14 | access to parameter e1 | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | E.cs:384:33:384:36 | null | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:33:384:36 | null | E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:16:386:22 | access to property Long | E.cs:386:27:386:33 | access to property Long | +| E.cs:386:16:386:33 | ... == ... | true | E.cs:386:27:386:33 | access to property Long | E.cs:386:16:386:22 | access to property Long | | Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:13:59:13 | access to parameter o | Forwarding.cs:59:18:59:21 | null | | Forwarding.cs:59:13:59:21 | ... == ... | true | Forwarding.cs:59:18:59:21 | null | Forwarding.cs:59:13:59:13 | access to parameter o | | Forwarding.cs:78:16:78:39 | call to method ReferenceEquals | true | Forwarding.cs:78:32:78:32 | access to parameter o | Forwarding.cs:78:35:78:38 | null | diff --git a/csharp/ql/test/query-tests/Nullness/Implications.expected b/csharp/ql/test/query-tests/Nullness/Implications.expected index cbb2de7cafc..d7a06795fc2 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.expected +++ b/csharp/ql/test/query-tests/Nullness/Implications.expected @@ -1236,6 +1236,26 @@ | E.cs:375:20:375:20 | access to local variable s | non-empty | E.cs:374:21:374:31 | ... as ... | non-empty | | E.cs:375:20:375:20 | access to local variable s | non-null | E.cs:374:21:374:31 | ... as ... | non-null | | E.cs:375:20:375:20 | access to local variable s | null | E.cs:374:21:374:31 | ... as ... | null | +| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:14:382:37 | ... && ... | false | +| E.cs:382:13:382:68 | ... \|\| ... | false | E.cs:382:44:382:67 | ... && ... | false | +| E.cs:382:14:382:23 | ... == ... | false | E.cs:382:14:382:15 | access to parameter e1 | non-null | +| E.cs:382:14:382:23 | ... == ... | true | E.cs:382:14:382:15 | access to parameter e1 | null | +| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:14:382:23 | ... == ... | true | +| E.cs:382:14:382:37 | ... && ... | true | E.cs:382:28:382:37 | ... != ... | true | +| E.cs:382:28:382:37 | ... != ... | false | E.cs:382:28:382:29 | access to parameter e2 | null | +| E.cs:382:28:382:37 | ... != ... | true | E.cs:382:28:382:29 | access to parameter e2 | non-null | +| E.cs:382:44:382:53 | ... != ... | false | E.cs:382:44:382:45 | access to parameter e1 | null | +| E.cs:382:44:382:53 | ... != ... | true | E.cs:382:44:382:45 | access to parameter e1 | non-null | +| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:44:382:53 | ... != ... | true | +| E.cs:382:44:382:67 | ... && ... | true | E.cs:382:58:382:67 | ... == ... | true | +| E.cs:382:58:382:67 | ... == ... | false | E.cs:382:58:382:59 | access to parameter e2 | non-null | +| E.cs:382:58:382:67 | ... == ... | true | E.cs:382:58:382:59 | access to parameter e2 | null | +| E.cs:384:13:384:22 | ... == ... | false | E.cs:384:13:384:14 | access to parameter e1 | non-null | +| E.cs:384:13:384:22 | ... == ... | true | E.cs:384:13:384:14 | access to parameter e1 | null | +| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:13:384:22 | ... == ... | true | +| E.cs:384:13:384:36 | ... && ... | true | E.cs:384:27:384:36 | ... == ... | true | +| E.cs:384:27:384:36 | ... == ... | false | E.cs:384:27:384:28 | access to parameter e2 | non-null | +| E.cs:384:27:384:36 | ... == ... | true | E.cs:384:27:384:28 | access to parameter e2 | null | | Forwarding.cs:9:13:9:30 | !... | false | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | true | | Forwarding.cs:9:13:9:30 | !... | true | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | false | | Forwarding.cs:9:14:9:14 | access to local variable s | empty | Forwarding.cs:7:20:7:23 | null | empty | diff --git a/csharp/ql/test/query-tests/Nullness/NullCheck.expected b/csharp/ql/test/query-tests/Nullness/NullCheck.expected index d9fcd0121f9..1c2b22ca6b5 100644 --- a/csharp/ql/test/query-tests/Nullness/NullCheck.expected +++ b/csharp/ql/test/query-tests/Nullness/NullCheck.expected @@ -264,6 +264,18 @@ | E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | false | true | | E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | true | false | | E.cs:372:13:372:23 | ... is ... | E.cs:372:13:372:13 | access to parameter o | true | false | +| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | false | false | +| E.cs:382:14:382:23 | ... == ... | E.cs:382:14:382:15 | access to parameter e1 | true | true | +| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | false | true | +| E.cs:382:28:382:37 | ... != ... | E.cs:382:28:382:29 | access to parameter e2 | true | false | +| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | false | true | +| E.cs:382:44:382:53 | ... != ... | E.cs:382:44:382:45 | access to parameter e1 | true | false | +| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | false | false | +| E.cs:382:58:382:67 | ... == ... | E.cs:382:58:382:59 | access to parameter e2 | true | true | +| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | false | false | +| E.cs:384:13:384:22 | ... == ... | E.cs:384:13:384:14 | access to parameter e1 | true | true | +| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | false | false | +| E.cs:384:27:384:36 | ... == ... | E.cs:384:27:384:28 | access to parameter e2 | true | true | | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | Forwarding.cs:9:14:9:14 | access to local variable s | false | false | | Forwarding.cs:14:13:14:32 | call to method IsNotNullOrEmpty | Forwarding.cs:14:13:14:13 | access to local variable s | true | false | | Forwarding.cs:19:14:19:23 | call to method IsNull | Forwarding.cs:19:14:19:14 | access to local variable s | false | false | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index acc3a29817c..4d4f9344986 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -355,6 +355,21 @@ nodes | E.cs:366:41:366:41 | access to parameter s | | E.cs:374:17:374:31 | SSA def(s) | | E.cs:375:20:375:20 | access to local variable s | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:24:380:25 | SSA param(e1) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:380:30:380:31 | SSA param(e2) | +| E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:382:44:382:67 | ... && ... | +| E.cs:382:44:382:67 | ... && ... | +| E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:386:16:386:17 | access to parameter e1 | +| E.cs:386:27:386:28 | access to parameter e2 | | Forwarding.cs:7:16:7:23 | SSA def(s) | | Forwarding.cs:14:9:17:9 | if (...) ... | | Forwarding.cs:19:9:22:9 | if (...) ... | @@ -688,6 +703,22 @@ edges | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:24:380:25 | SSA param(e1) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:28:382:29 | access to parameter e2 | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:380:30:380:31 | SSA param(e2) | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:28:382:29 | access to parameter e2 | E.cs:382:44:382:67 | ... && ... | +| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... | +| E.cs:382:44:382:67 | ... && ... | E.cs:384:9:385:24 | if (...) ... | +| E.cs:384:9:385:24 | if (...) ... | E.cs:384:27:384:28 | access to parameter e2 | +| E.cs:384:9:385:24 | if (...) ... | E.cs:386:27:386:28 | access to parameter e2 | +| E.cs:384:27:384:28 | access to parameter e2 | E.cs:386:16:386:17 | access to parameter e1 | | Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... | | Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... | | Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... | @@ -790,6 +821,12 @@ edges | E.cs:349:9:349:9 | access to local variable x | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | Variable $@ may be null here because of $@ assignment. | E.cs:348:17:348:17 | x | x | E.cs:348:17:348:36 | dynamic x = ... | this | | E.cs:366:41:366:41 | access to parameter s | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | Variable $@ may be null here because the parameter has a null default value. | E.cs:366:28:366:28 | s | s | E.cs:366:32:366:35 | null | this | | E.cs:375:20:375:20 | access to local variable s | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | Variable $@ may be null here because of $@ assignment. | E.cs:374:17:374:17 | s | s | E.cs:374:17:374:31 | String s = ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:14:382:23 | ... == ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:382:44:382:53 | ... != ... | this | +| E.cs:386:16:386:17 | access to parameter e1 | E.cs:380:24:380:25 | SSA param(e1) | E.cs:386:16:386:17 | access to parameter e1 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:24:380:25 | e1 | e1 | E.cs:384:13:384:22 | ... == ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:28:382:37 | ... != ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:382:58:382:67 | ... == ... | this | +| E.cs:386:27:386:28 | access to parameter e2 | E.cs:380:30:380:31 | SSA param(e2) | E.cs:386:27:386:28 | access to parameter e2 | Variable $@ may be null here as suggested by $@ null check. | E.cs:380:30:380:31 | e2 | e2 | E.cs:384:27:384:36 | ... == ... | this | | GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null here because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this | | NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null here because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this | | StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null here because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this | diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs index 2a7cc3ae232..c0d56d1337e 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.cs @@ -2,10 +2,13 @@ using System; using System.Web; +using System.Web.UI.WebControls; public class StackTraceHandler : IHttpHandler { bool b; + TextBox textBox; + public void ProcessRequest(HttpContext ctx) { try @@ -34,6 +37,11 @@ public class StackTraceHandler : IHttpHandler // GOOD: log the stack trace, and send back a non-revealing response log("Exception occurred", ex); ctx.Response.Write("Exception occurred"); + + textBox.Text = ex.InnerException.StackTrace; // BAD + textBox.Text = ex.StackTrace; // BAD + textBox.Text = ex.ToString(); // BAD + textBox.Text = ex.Message; // GOOD return; } diff --git a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected index 3cdd0f50449..492a61dd038 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected +++ b/csharp/ql/test/query-tests/Security Features/CWE-209/ExceptionInformationExposure.expected @@ -1,14 +1,20 @@ edges -| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | +| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | nodes -| ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception | -| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | semmle.label | call to method ToString | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | semmle.label | access to local variable ex | -| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | semmle.label | access to property StackTrace | -| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | semmle.label | call to method ToString | +| ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | semmle.label | access to local variable ex : Exception | +| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | semmle.label | call to method ToString | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | semmle.label | access to local variable ex | +| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | semmle.label | access to property StackTrace | +| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | semmle.label | call to method ToString | +| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | semmle.label | call to method ToString | #select -| ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:44 | call to method ToString | call to method ToString | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:18:32:18:33 | access to local variable ex | access to local variable ex : Exception | -| ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:20:32:20:33 | access to local variable ex | access to local variable ex | -| ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:22:32:22:44 | access to property StackTrace | access to property StackTrace | -| ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:44 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex : Exception | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:21:32:21:33 | access to local variable ex | access to local variable ex : Exception | +| ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:23:32:23:33 | access to local variable ex | access to local variable ex | +| ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:25:32:25:44 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:41:28:41:55 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:42:28:42:40 | access to property StackTrace | access to property StackTrace | +| ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:43:28:43:40 | call to method ToString | call to method ToString | +| ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | Exception information from $@ flows to here, and is exposed to the user. | ExceptionInformationExposure.cs:49:28:49:55 | call to method ToString | call to method ToString | diff --git a/docs/language/README.rst b/docs/language/README.rst index 48beeed5791..ecc9d4d0c09 100644 --- a/docs/language/README.rst +++ b/docs/language/README.rst @@ -109,7 +109,7 @@ examples, see the `template slide deck `__. There, you can also find the documentation for the CodeQL CLI, the CodeQL extension for Visual Studio Code, and LGTM Enterprise. diff --git a/docs/language/learn-ql/beginner/fire-1.rst b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst similarity index 73% rename from docs/language/learn-ql/beginner/fire-1.rst rename to docs/language/learn-ql/beginner/catch-the-fire-starter.rst index d5427b56d5f..72f3f4f7685 100644 --- a/docs/language/learn-ql/beginner/fire-1.rst +++ b/docs/language/learn-ql/beginner/catch-the-fire-starter.rst @@ -1,5 +1,7 @@ -Catch the fire starter: Classes and predicates -============================================== +Catch the fire starter +====================== + +Learn about QL predicates and classes to solve your second mystery as a QL detective. Just as you've successfully found the thief and returned the golden crown to the castle, another terrible crime is committed. Early in the morning, a few people start a fire in a field in the north of the village and destroy all the crops! @@ -101,6 +103,50 @@ Now try applying ``isAllowedIn(string region)`` to a person ``p``. If ``p`` is n You know that the fire starters live in the south *and* that they must have been able to travel to the north. Write a query to find the possible suspects. You could also extend the ``select`` clause to list the age of the suspects. That way you can clearly see that all the children have been excluded from the list. -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ -Continue to the :doc:`next page ` to gather more clues and find out which of your suspects started the fire... +You can now continue to gather more clues and find out which of your suspects started the fire... + +Identify the bald bandits +------------------------- + +You ask the northerners if they have any more information about the fire starters. Luckily, you have a witness! The farmer living next to the field saw two people run away just after the fire started. He only saw the tops of their heads, and noticed that they were both bald. + +This is a very helpful clue. Remember that you wrote a QL query to select all bald people: + +.. code-block:: ql + + from Person p + where not exists (string c | p.getHairColor() = c) + select p + +To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``. + +.. code-block:: ql + + predicate isBald(Person p) { + not exists (string c | p.getHairColor() = c) + } + +The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with: + +.. code-block:: ql + + from Person p + where isBald(p) + select p + +The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example—that would cause an error. + +You can now write a query to select the bald southerners who are allowed into the north. + +➤ `See the answer in the query console on LGTM.com `__ + +You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. + +Further reading +--------------- + +- Find out who will be the new ruler of the village in the :doc:`next tutorial `. +- Learn more about predicates and classes in the `QL language reference `__. +- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/ql-etudes/river-crossing.rst b/docs/language/learn-ql/beginner/cross-the-river.rst similarity index 95% rename from docs/language/learn-ql/ql-etudes/river-crossing.rst rename to docs/language/learn-ql/beginner/cross-the-river.rst index fef3363a08b..3f5307d98d5 100644 --- a/docs/language/learn-ql/ql-etudes/river-crossing.rst +++ b/docs/language/learn-ql/beginner/cross-the-river.rst @@ -1,7 +1,10 @@ -River crossing puzzle -##################### +Cross the river +=============== -The aim of this tutorial is to write a query that finds a solution to the following classical logic puzzle: +Use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. + +Introduction +------------ .. pull-quote:: @@ -248,15 +251,15 @@ Here are some more example queries that solve the river crossing puzzle: #. This query uses a modified ``path`` variable to describe the resulting path in more detail. - ➤ `See solution in the query console `__ + ➤ `See solution in the query console on LGTM.com `__ #. This query models the man and the cargo items in a different way, using an `abstract `__ class and predicate. It also displays the resulting path in a more visual way. - ➤ `See solution in the query console `__ + ➤ `See solution in the query console on LGTM.com `__ #. This query introduces `algebraic datatypes `__ to model the situation, instead of defining everything as a subclass of ``string``. - ➤ `See solution in the query console `__ \ No newline at end of file + ➤ `See solution in the query console on LGTM.com `__ \ No newline at end of file diff --git a/docs/language/learn-ql/beginner/heir.rst b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst similarity index 93% rename from docs/language/learn-ql/beginner/heir.rst rename to docs/language/learn-ql/beginner/crown-the-rightful-heir.rst index 42589f03125..df3cd61fde9 100644 --- a/docs/language/learn-ql/beginner/heir.rst +++ b/docs/language/learn-ql/beginner/crown-the-rightful-heir.rst @@ -1,6 +1,11 @@ Crown the rightful heir ======================= +This is a QL detective puzzle that shows you how to use recursion in QL to write more complex queries. + +King Basil's heir +----------------- + Phew! No more crimes in the village—you can finally leave the village and go home. But then... During your last night in the village, the old king—the great King Basil—dies in his sleep and there is chaos everywhere! @@ -9,9 +14,6 @@ The king never married and he had no children, so nobody knows who should inheri Eventually you decide to stay in the village to resolve the argument and find the true heir to the throne. -King Basil's heir ------------------ - You want to find out if anyone in the village is actually related to the king. This seems like a difficult task at first, but you start work confidently. You know the villagers quite well by now, and you have a list of all the parents in the village and their children. To find out more about the king and his family, you get access to the castle and find some old family trees. You also include these relations in your database to see if anyone in the king's family is still alive. @@ -125,7 +127,7 @@ Here is one way to define ``relativeOf()``: Don't forget to use the predicate ``isDeceased()`` to find relatives that are still alive. -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ Select the true heir -------------------- @@ -136,9 +138,9 @@ To decide who should inherit the king's fortune, the villagers carefully read th *"The heir to the throne is the closest living relative of the king. Any person with a criminal record will not be considered. If there are multiple candidates, the oldest person is the heir."* -As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). +As your final challenge, define a predicate ``hasCriminalRecord`` so that ``hasCriminalRecord(p)`` holds if ``p`` is any of the criminals you unmasked earlier (in the :doc:`Find the thief ` and :doc:`Catch the fire starter ` tutorials). -➤ `See the answer in the query console `__ +➤ `See the answer in the query console on LGTM.com `__ Experimental explorations ------------------------- @@ -156,9 +158,9 @@ You could also try writing more of your own QL queries to find interesting facts - Do all villagers live in the same region of the village as their parents? - Find out whether there are any time travelers in the village! (Hint: Look for "impossible" family relations.) -What next? ----------- +Further reading +--------------- -- Learn more about recursion in the `QL language handbook `__. -- Put your QL skills to the test and solve the :doc:`River crossing puzzle <../ql-etudes/river-crossing>`. +- Learn more about recursion in the `QL language reference `__. +- Put your QL skills to the test and solve the :doc:`River crossing puzzle `. - Start using QL to analyze projects. See :doc:`Learning CodeQL <../../index>` for a summary of the available languages and resources. diff --git a/docs/language/learn-ql/beginner/find-the-thief.rst b/docs/language/learn-ql/beginner/find-the-thief.rst new file mode 100644 index 00000000000..02f19cce325 --- /dev/null +++ b/docs/language/learn-ql/beginner/find-the-thief.rst @@ -0,0 +1,297 @@ +Find the thief +============== + +Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. + +Introduction +------------ + +There is a small village hidden away in the mountains. The village is divided into four parts—north, south, east, and west—and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown! + +You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details. + ++------+-----+------------+--------+----------+ +| Name | Age | Hair color | Height | Location | ++======+=====+============+========+==========+ +| ... | ... | ... | ... | ... | ++------+-----+------------+--------+----------+ + +Sadly, you still have no idea who could have stolen the crown so you walk around the village to find clues. The villagers act very suspiciously and you are convinced they have information about the thief. They refuse to share their knowledge with you directly, but they reluctantly agree to answer questions. They are still not very talkative and **only answer questions with 'yes' or 'no'**. + +You start asking some creative questions and making notes of the answers so you can compare them with your information later: + ++------+--------------------------------------------------------------------+--------+ +| | Question | Answer | ++======+====================================================================+========+ +| (1) | Is the thief taller than 150 cm? | yes | ++------+--------------------------------------------------------------------+--------+ +| (2) | Does the thief have blond hair? | no | ++------+--------------------------------------------------------------------+--------+ +| (3) | Is the thief bald? | no | ++------+--------------------------------------------------------------------+--------+ +| (4) | Is the thief younger than 30? | no | ++------+--------------------------------------------------------------------+--------+ +| (5) | Does the thief live east of the castle? | yes | ++------+--------------------------------------------------------------------+--------+ +| (6) | Does the thief have black or brown hair? | yes | ++------+--------------------------------------------------------------------+--------+ +| (7) | Is the thief taller than 180cm and shorter than 190cm? | no | ++------+--------------------------------------------------------------------+--------+ +| (8) | Is the thief the tallest person in the village? | no | ++------+--------------------------------------------------------------------+--------+ +| (9) | Is the thief shorter than the average villager? | yes | ++------+--------------------------------------------------------------------+--------+ +| (10) | Is the thief the oldest person in the eastern part of the village? | yes | ++------+--------------------------------------------------------------------+--------+ + +There is too much information to search through by hand, so you decide to use your newly acquired QL skills to help you with your investigation... + +#. Open the `query console on LGTM.com `__ to get started. +#. Select a language and a demo project. For this tutorial, any language and project will do. +#. Delete the default code ``import select "hello world"``. + +QL libraries +------------ + +We've defined a number of QL `predicates `__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age. + ++--------------------+----------------------------------------------------------------------------------------+ +| Predicate | Description | ++====================+========================================================================================+ +| ``getAge()`` | returns the age of the person (in years) as an ``int`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getHairColor()`` | returns the hair color of the person as a ``string`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getHeight()`` | returns the height of the person (in cm) as a ``float`` | ++--------------------+----------------------------------------------------------------------------------------+ +| ``getLocation()`` | returns the location of the person's home (north, south, east or west) as a ``string`` | ++--------------------+----------------------------------------------------------------------------------------+ + +We've stored these predicates in the QL library ``tutorial.qll``. To access this library, type ``import tutorial`` in the query console. + +Libraries are convenient for storing commonly used predicates. This saves you from defining a predicate every time you need it. Instead you can just ``import`` the library and use the predicate directly. Once you have imported the library, you can apply any of these predicates to an expression by appending it. + +For example, ``t.getHeight()`` applies ``getHeight()`` to ``t`` and returns the height of ``t``. + +Start the search +----------------- + +The villagers answered "yes" to the question "Is the thief taller than 150cm?" To use this information, you can write the following query to list all villagers taller than 150cm. These are all possible suspects. + +.. code-block:: ql + + from Person t + where t.getHeight() > 150 + select t + +The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type `__ of ``t`` is ``Person``. + +Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries: + +Logical connectives +------------------- + +Using `logical connectives `__, you can write more complex queries that combine different pieces of information. + +For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates: + +.. code-block:: ql + + where t.getAge() > 30 and t.getHairColor() = "brown" + +.. pull-quote:: + + Note + + The predicate ``getHairColor()`` returns a ``string``, so we need to include quotation marks around the result ``"brown"``. + +If the thief does *not* live north of the castle, you can use: + +.. code-block:: ql + + where not t.getLocation() = "north" + +If the thief has brown hair *or* black hair, you can use: + +.. code-block:: ql + + where t.getHairColor() = "brown" or t.getHairColor() = "black" + +You can also combine these connectives into longer statements: + +.. code-block:: ql + + where t.getAge() > 30 + and (t.getHairColor() = "brown" or t.getHairColor() = "black") + and not t.getLocation() = "north" + +.. pull-quote:: + + Note + + We've placed parentheses around the ``or`` clause to make sure that the query is evaluated as intended. Without parentheses, the connective ``and`` takes precedence over ``or``. + +Predicates don't always return exactly one value. For example, if a person ``p`` has black hair which is turning gray, ``p.getHairColor()`` will return two values: black and gray. + +What if the thief is bald? In that case, the thief has no hair, so the ``getHairColor()`` predicate simply doesn't return any results! + +If you know that the thief definitely isn't bald, then there must be a color that matches the thief's hair color. One way to express this in QL is to introduce a new variable ``c`` of type ``string`` and select those ``t`` where ``t.getHairColor()`` matches a value of ``c``. + +.. code-block:: ql + + from Person t, string c + where t.getHairColor() = c + select t + +Notice that we have only temporarily introduced the variable ``c`` and we didn't need it at all in the ``select`` clause. In this case, it is better to use ``exists``: + +.. code-block:: ql + + from Person t + where exists(string c | t.getHairColor() = c) + select t + +``exists`` introduces a temporary variable ``c`` of type ``string`` and holds only if there is at least one ``string c`` that satisfies ``t.getHairColor() = c``. + +.. pull-quote:: + + Note + + If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier `__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``. + +The real investigation +---------------------- + +You are now ready to track down the thief! Using the examples above, write a query to find the people who satisfy the answers to the first eight questions: + ++---+--------------------------------------------------------+--------+ +| | Question | Answer | ++===+========================================================+========+ +| 1 | Is the thief taller than 150 cm? | yes | ++---+--------------------------------------------------------+--------+ +| 2 | Does the thief have blond hair? | no | ++---+--------------------------------------------------------+--------+ +| 3 | Is the thief bald? | no | ++---+--------------------------------------------------------+--------+ +| 4 | Is the thief younger than 30? | no | ++---+--------------------------------------------------------+--------+ +| 5 | Does the thief live east of the castle? | yes | ++---+--------------------------------------------------------+--------+ +| 6 | Does the thief have black or brown hair? | yes | ++---+--------------------------------------------------------+--------+ +| 7 | Is the thief taller than 180cm and shorter than 190cm? | no | ++---+--------------------------------------------------------+--------+ +| 8 | Is the thief the oldest person in the village? | no | ++---+--------------------------------------------------------+--------+ + +Hints +^^^^^ + +#. Don't forget to ``import tutorial``! +#. Translate each question into QL separately. Look at the examples above if you get stuck. +#. For question 3, remember that a bald person does not have a hair color. +#. For question 8, note that if a person is *not* the oldest, then there is at least one person who is older than them. +#. Combine the conditions using logical connectives to get a query of the form: + +.. code-block:: ql + + import tutorial + + from Person t + where and + not and + ... + select t + +Once you have finished, you will have a list of possible suspects. One of those people must be the thief! + +➤ `See the answer in the query console on LGTM.com `__ + +.. pull-quote:: + + Note + + In the answer, we used ``/*`` and ``*/`` to label the different parts of the query. Any text surrounded by ``/*`` and ``*/`` is not evaluated as part of the QL code, but is just a *comment*. + +You are getting closer to solving the mystery! Unfortunately, you still have quite a long list of suspects... To find out which of your suspects is the thief, you must gather more information and refine your query in the next step. + +More advanced queries +--------------------- + +What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates `__. + +In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is: + +.. code-block:: ql + + ( | | ) + +For example, you can use the ``max`` aggregate to find the age of the oldest person in the village: + +.. code-block:: ql + + max(int i | exists(Person p | p.getAge() = i) | i) + +This aggregate considers all integers ``i``, limits ``i`` to values that match the ages of people in the village, and then returns the largest matching integer. + +But how can you use this in an actual query? + +If the thief is the oldest person in the village, then you know that the thief's age is equal to the maximum age of the villagers: + +.. code-block:: ql + + from Person t + where t.getAge() = max(int i | exists(Person p | p.getAge() = i) | i) + select t + +This general aggregate syntax is quite long and inconvenient. In most cases, you can omit certain parts of the aggregate. A particularly helpful QL feature is *ordered aggregation*. This allows you to order the expression using ``order by``. + +For example, selecting the oldest villager becomes much simpler if you use an ordered aggregate. + +.. code-block:: ql + + select max(Person p | | p order by p.getAge()) + +The ordered aggregate considers every person ``p`` and selects the person with the maximum age. In this case, there are no restrictions on what people to consider, so the ```` clause is empty. Note that if there are several people with the same maximum age, the query lists all of them. + +Here are some more examples of aggregates: + ++-------------------------------------------------------------------------+---------------------------------------------------+ +| Example | Result | ++=========================================================================+===================================================+ +| ``min(Person p | p.getLocation() = "east" | p order by p.getHeight())`` | shortest person in the east of the village | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``count(Person p | p.getLocation() = "south" | p)`` | number of people in the south of the village | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``avg(Person p | | p.getHeight())`` | average height of the villagers | ++-------------------------------------------------------------------------+---------------------------------------------------+ +| ``sum(Person p | p.getHairColor() = "brown" | p.getAge())`` | combined age of all the villagers with brown hair | ++-------------------------------------------------------------------------+---------------------------------------------------+ + +Capture the culprit +------------------- + +You can now translate the remaining questions into QL: + ++-----+--------------------------------------------------------------------+--------+ +| | Question | Answer | ++=====+====================================================================+========+ +| ... | ... | ... | ++-----+--------------------------------------------------------------------+--------+ +| 9 | Is the thief the tallest person in the village? | no | ++-----+--------------------------------------------------------------------+--------+ +| 10 | Is the thief shorter than the average villager? | yes | ++-----+--------------------------------------------------------------------+--------+ +| 11 | Is the thief the oldest person in the eastern part of the village? | yes | ++-----+--------------------------------------------------------------------+--------+ + +Have you found the thief? + +➤ `See the answer in the query console on LGTM.com `__ + +Further reading +--------------- + +- Help the villagers track down another criminal in the :doc:`next tutorial `. +- Find out more about the concepts you discovered in this tutorial in the `QL language reference `__. +- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/find-thief-1.rst b/docs/language/learn-ql/beginner/find-thief-1.rst deleted file mode 100644 index 3df6c108837..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-1.rst +++ /dev/null @@ -1,71 +0,0 @@ -Find the thief: Introduction -============================ - -There is a small village hidden away in the mountains. The village is divided into four parts—north, south, east, and west—and in the center stands a dark and mysterious castle... Inside the castle, locked away in the highest tower, lies the king's valuable golden crown. One night, a terrible crime is committed. A thief breaks into the tower and steals the crown! - -You know that the thief must live in the village, since nobody else knew about the crown. After some expert detective work, you obtain a list of all the people in the village and some of their personal details. - -+------+-----+------------+--------+----------+ -| Name | Age | Hair color | Height | Location | -+======+=====+============+========+==========+ -| ... | ... | ... | ... | ... | -+------+-----+------------+--------+----------+ - -Sadly, you still have no idea who could have stolen the crown so you walk around the village to find clues. The villagers act very suspiciously and you are convinced they have information about the thief. They refuse to share their knowledge with you directly, but they reluctantly agree to answer questions. They are still not very talkative and **only answer questions with 'yes' or 'no'**. - -You start asking some creative questions and making notes of the answers so you can compare them with your information later: - -+------+--------------------------------------------------------------------+--------+ -| | Question | Answer | -+======+====================================================================+========+ -| (1) | Is the thief taller than 150 cm? | yes | -+------+--------------------------------------------------------------------+--------+ -| (2) | Does the thief have blond hair? | no | -+------+--------------------------------------------------------------------+--------+ -| (3) | Is the thief bald? | no | -+------+--------------------------------------------------------------------+--------+ -| (4) | Is the thief younger than 30? | no | -+------+--------------------------------------------------------------------+--------+ -| (5) | Does the thief live east of the castle? | yes | -+------+--------------------------------------------------------------------+--------+ -| (6) | Does the thief have black or brown hair? | yes | -+------+--------------------------------------------------------------------+--------+ -| (7) | Is the thief taller than 180cm and shorter than 190cm? | no | -+------+--------------------------------------------------------------------+--------+ -| (8) | Is the thief the tallest person in the village? | no | -+------+--------------------------------------------------------------------+--------+ -| (9) | Is the thief shorter than the average villager? | yes | -+------+--------------------------------------------------------------------+--------+ -| (10) | Is the thief the oldest person in the eastern part of the village? | yes | -+------+--------------------------------------------------------------------+--------+ - -There is too much information to search through by hand, so you decide to use your newly acquired QL skills to help you with your investigation... - -#. Open the `query console `__ to get started. -#. Select a language and a demo project. For this tutorial, any language and project will do. -#. Delete the default code ``import select "hello world"``. - -QL libraries ------------- - -We've defined a number of QL `predicates `__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age. - -+--------------------+----------------------------------------------------------------------------------------+ -| Predicate | Description | -+====================+========================================================================================+ -| ``getAge()`` | returns the age of the person (in years) as an ``int`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getHairColor()`` | returns the hair color of the person as a ``string`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getHeight()`` | returns the height of the person (in cm) as a ``float`` | -+--------------------+----------------------------------------------------------------------------------------+ -| ``getLocation()`` | returns the location of the person's home (north, south, east or west) as a ``string`` | -+--------------------+----------------------------------------------------------------------------------------+ - -We've stored these predicates in the QL library ``tutorial.qll``. To access this library, type ``import tutorial`` in the query console. - -Libraries are convenient for storing commonly used predicates. This saves you from defining a predicate every time you need it. Instead you can just ``import`` the library and use the predicate directly. Once you have imported the library, you can apply any of these predicates to an expression by appending it. - -For example, ``t.getHeight()`` applies ``getHeight()`` to ``t`` and returns the height of ``t``. - -Continue to the next page to :doc:`start the investigation `. diff --git a/docs/language/learn-ql/beginner/find-thief-2.rst b/docs/language/learn-ql/beginner/find-thief-2.rst deleted file mode 100644 index b31f978d36a..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-2.rst +++ /dev/null @@ -1,141 +0,0 @@ -Find the thief: Start the search -================================ - -The villagers answered "yes" to the question "Is the thief taller than 150cm?" To use this information, you can write the following query to list all villagers taller than 150cm. These are all possible suspects. - -.. code-block:: ql - - from Person t - where t.getHeight() > 150 - select t - -The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type `__ of ``t`` is ``Person``. - -Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries: - -Logical connectives -------------------- - -Using `logical connectives `__, you can write more complex queries that combine different pieces of information. - -For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates: - -.. code-block:: ql - - where t.getAge() > 30 and t.getHairColor() = "brown" - -.. pull-quote:: - - Note - - The predicate ``getHairColor()`` returns a ``string``, so we need to include quotation marks around the result ``"brown"``. - -If the thief does *not* live north of the castle, you can use: - -.. code-block:: ql - - where not t.getLocation() = "north" - -If the thief has brown hair *or* black hair, you can use: - -.. code-block:: ql - - where t.getHairColor() = "brown" or t.getHairColor() = "black" - -You can also combine these connectives into longer statements: - -.. code-block:: ql - - where t.getAge() > 30 - and (t.getHairColor() = "brown" or t.getHairColor() = "black") - and not t.getLocation() = "north" - -.. pull-quote:: - - Note - - We've placed parentheses around the ``or`` clause to make sure that the query is evaluated as intended. Without parentheses, the connective ``and`` takes precedence over ``or``. - -Predicates don't always return exactly one value. For example, if a person ``p`` has black hair which is turning gray, ``p.getHairColor()`` will return two values: black and gray. - -What if the thief is bald? In that case, the thief has no hair, so the ``getHairColor()`` predicate simply doesn't return any results! - -If you know that the thief definitely isn't bald, then there must be a color that matches the thief's hair color. One way to express this in QL is to introduce a new variable ``c`` of type ``string`` and select those ``t`` where ``t.getHairColor()`` matches a value of ``c``. - -.. code-block:: ql - - from Person t, string c - where t.getHairColor() = c - select t - -Notice that we have only temporarily introduced the variable ``c`` and we didn't need it at all in the ``select`` clause. In this case, it is better to use ``exists``: - -.. code-block:: ql - - from Person t - where exists(string c | t.getHairColor() = c) - select t - -``exists`` introduces a temporary variable ``c`` of type ``string`` and holds only if there is at least one ``string c`` that satisfies ``t.getHairColor() = c``. - -.. pull-quote:: - - Note - - If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier `__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``. - -The real investigation ----------------------- - -You are now ready to track down the thief! Using the examples above, write a query to find the people who satisfy the answers to the first eight questions: - -+---+--------------------------------------------------------+--------+ -| | Question | Answer | -+===+========================================================+========+ -| 1 | Is the thief taller than 150 cm? | yes | -+---+--------------------------------------------------------+--------+ -| 2 | Does the thief have blond hair? | no | -+---+--------------------------------------------------------+--------+ -| 3 | Is the thief bald? | no | -+---+--------------------------------------------------------+--------+ -| 4 | Is the thief younger than 30? | no | -+---+--------------------------------------------------------+--------+ -| 5 | Does the thief live east of the castle? | yes | -+---+--------------------------------------------------------+--------+ -| 6 | Does the thief have black or brown hair? | yes | -+---+--------------------------------------------------------+--------+ -| 7 | Is the thief taller than 180cm and shorter than 190cm? | no | -+---+--------------------------------------------------------+--------+ -| 8 | Is the thief the oldest person in the village? | no | -+---+--------------------------------------------------------+--------+ - -Hints -^^^^^ - -#. Don't forget to ``import tutorial``! -#. Translate each question into QL separately. Look at the examples above if you get stuck. -#. For question 3, remember that a bald person does not have a hair color. -#. For question 8, note that if a person is *not* the oldest, then there is at least one person who is older than them. -#. Combine the conditions using logical connectives to get a query of the form: - -.. code-block:: ql - - import tutorial - - from Person t - where and - not and - ... - select t - -Once you have finished, you will have a list of possible suspects. One of those people must be the thief! - -➤ `See the answer in the query console `__ - -.. pull-quote:: - - Note - - In the answer, we used ``/*`` and ``*/`` to label the different parts of the query. Any text surrounded by ``/*`` and ``*/`` is not evaluated as part of the QL code, but is just a *comment*. - -You are getting closer to solving the mystery! Unfortunately, you still have quite a long list of suspects... To find out which of your suspects is the thief, you must gather more information and refine your query in the :doc:`next step `. diff --git a/docs/language/learn-ql/beginner/find-thief-3.rst b/docs/language/learn-ql/beginner/find-thief-3.rst deleted file mode 100644 index f8323147cf1..00000000000 --- a/docs/language/learn-ql/beginner/find-thief-3.rst +++ /dev/null @@ -1,80 +0,0 @@ -Find the thief: More advanced queries -===================================== - -What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates `__. - -In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is: - -.. code-block:: ql - - ( | | ) - -For example, you can use the ``max`` aggregate to find the age of the oldest person in the village: - -.. code-block:: ql - - max(int i | exists(Person p | p.getAge() = i) | i) - -This aggregate considers all integers ``i``, limits ``i`` to values that match the ages of people in the village, and then returns the largest matching integer. - -But how can you use this in an actual query? - -If the thief is the oldest person in the village, then you know that the thief's age is equal to the maximum age of the villagers: - -.. code-block:: ql - - from Person t - where t.getAge() = max(int i | exists(Person p | p.getAge() = i) | i) - select t - -This general aggregate syntax is quite long and inconvenient. In most cases, you can omit certain parts of the aggregate. A particularly helpful QL feature is *ordered aggregation*. This allows you to order the expression using ``order by``. - -For example, selecting the oldest villager becomes much simpler if you use an ordered aggregate. - -.. code-block:: ql - - select max(Person p | | p order by p.getAge()) - -The ordered aggregate considers every person ``p`` and selects the person with the maximum age. In this case, there are no restrictions on what people to consider, so the ```` clause is empty. Note that if there are several people with the same maximum age, the query lists all of them. - -Here are some more examples of aggregates: - -+-------------------------------------------------------------------------+---------------------------------------------------+ -| Example | Result | -+=========================================================================+===================================================+ -| ``min(Person p | p.getLocation() = "east" | p order by p.getHeight())`` | shortest person in the east of the village | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``count(Person p | p.getLocation() = "south" | p)`` | number of people in the south of the village | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``avg(Person p | | p.getHeight())`` | average height of the villagers | -+-------------------------------------------------------------------------+---------------------------------------------------+ -| ``sum(Person p | p.getHairColor() = "brown" | p.getAge())`` | combined age of all the villagers with brown hair | -+-------------------------------------------------------------------------+---------------------------------------------------+ - -Capture the culprit -------------------- - -You can now translate the remaining questions into QL: - -+-----+--------------------------------------------------------------------+--------+ -| | Question | Answer | -+=====+====================================================================+========+ -| ... | ... | ... | -+-----+--------------------------------------------------------------------+--------+ -| 9 | Is the thief the tallest person in the village? | no | -+-----+--------------------------------------------------------------------+--------+ -| 10 | Is the thief shorter than the average villager? | yes | -+-----+--------------------------------------------------------------------+--------+ -| 11 | Is the thief the oldest person in the eastern part of the village? | yes | -+-----+--------------------------------------------------------------------+--------+ - -Have you found the thief? - -➤ `See the answer in the query console `__ - -What next? ----------- - -- Help the villagers track down another criminal in the :doc:`next tutorial `. -- Find out more about the concepts you discovered in this tutorial in the `QL language handbook `__. -- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/fire-2.rst b/docs/language/learn-ql/beginner/fire-2.rst deleted file mode 100644 index 0f5312e69f0..00000000000 --- a/docs/language/learn-ql/beginner/fire-2.rst +++ /dev/null @@ -1,43 +0,0 @@ -Catch the fire starter: Bald bandits -==================================== - -You ask the northerners if they have any more information about the fire starters. Luckily, you have a witness! The farmer living next to the field saw two people run away just after the fire started. He only saw the tops of their heads, and noticed that they were both bald. - -This is a very helpful clue. Remember that you wrote a QL query to select all bald people: - -.. code-block:: ql - - from Person p - where not exists (string c | p.getHairColor() = c) - select p - -To avoid having to type ``not exists (string c | p.getHairColor() = c)`` every time you want to select a bald person, you can instead define another new predicate ``isBald``. - -.. code-block:: ql - - predicate isBald(Person p) { - not exists (string c | p.getHairColor() = c) - } - -The property ``isBald(p)`` holds whenever ``p`` is bald, so you can replace the previous query with: - -.. code-block:: ql - - from Person p - where isBald(p) - select p - -The predicate ``isBald`` is defined to take a ``Person``, so it can also take a ``Southerner``, as ``Southerner`` is a subtype of ``Person``. It can't take an ``int`` for example—that would cause an error. - -You can now write a query to select the bald southerners who are allowed into the north. - -➤ `See the answer in the query console `__ - -You have found the two fire starters! They are arrested and the villagers are once again impressed with your work. - -What next? ----------- - -- Find out who will be the new ruler of the village in the :doc:`next tutorial `. -- Learn more about predicates and classes in the `QL language handbook `__. -- Explore the libraries that help you get data about code in :doc:`Learning CodeQL <../../index>`. diff --git a/docs/language/learn-ql/beginner/ql-tutorials.rst b/docs/language/learn-ql/beginner/ql-tutorials.rst index 2f3d6cc5e5d..a8dd35ff617 100644 --- a/docs/language/learn-ql/beginner/ql-tutorials.rst +++ b/docs/language/learn-ql/beginner/ql-tutorials.rst @@ -1,27 +1,19 @@ -QL detective tutorials -====================== +QL tutorials +============ + +Solve puzzles to learn the basics of QL before you analyze code with CodeQL. The tutorials teach you how to write queries and introduce you to key logic concepts along the way. .. toctree:: - :glob: :hidden: - ./* + ../introduction-to-ql + find-the-thief + catch-the-fire-starter + crown-the-rightful-heir + cross-the-river -Welcome to the detective tutorials! These are aimed at complete beginners who would like to learn the basics of QL, -before analyzing code with CodeQL. -The tutorials teach you how to write queries and introduce you to key logic concepts along the way. - -We recommend you first read the :doc:`Introduction to QL <../introduction-to-ql>` page for a description of the language and -some simple examples. - -Currently the following detective tutorials are available: - -- :doc:`Find the thief `—a three part mystery that introduces logical connectives, quantifiers, and aggregates -- :doc:`Catch the fire starter `—an intriguing search that introduces predicates and classes -- :doc:`Crown the rightful heir `—a detective puzzle that introduces recursion - -Further resources ------------------ - -- For a summary of available learning resources, see :doc:`Learning CodeQL <../../index>`. -- For an overview of the important concepts in QL, see the `QL language handbook `__. +- :doc:`Introduction to QL <../introduction-to-ql>`: Work through some simple exercises and examples to learn about the basics of QL and CodeQL. +- :doc:`Find the thief `: Take on the role of a detective to find the thief in this fictional village. You will learn how to use logical connectives, quantifiers, and aggregates in QL along the way. +- :doc:`Catch the fire starter `: Learn about QL predicates and classes to solve your second mystery as a QL detective. +- :doc:`Crown the rightful heir `: This is a QL detective puzzle that shows you how to use recursion in QL to write more complex queries. +- :doc:`Cross the river `: Use common QL features to write a query that finds a solution to the "River crossing" logic puzzle. diff --git a/docs/language/learn-ql/ql-etudes/river-crossing-1.ql b/docs/language/learn-ql/beginner/river-crossing-1.ql similarity index 100% rename from docs/language/learn-ql/ql-etudes/river-crossing-1.ql rename to docs/language/learn-ql/beginner/river-crossing-1.ql diff --git a/docs/language/learn-ql/ql-etudes/river-crossing.ql b/docs/language/learn-ql/beginner/river-crossing.ql similarity index 100% rename from docs/language/learn-ql/ql-etudes/river-crossing.ql rename to docs/language/learn-ql/beginner/river-crossing.ql diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 016efa50d67..553423bb47e 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -1,15 +1,14 @@ -Tutorial: Conversions and classes -================================= +Conversions and classes in C and C++ +==================================== -Overview --------- - -This topic contains worked examples of how to write queries using the CodeQL library classes for C/C++ conversions and classes. +You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed. Conversions ----------- -Let us take a look at the ``Conversion`` class in the standard library: +In C and C++, conversions change the type of an expression. They may be implicit conversions generated by the compiler, or explicit conversions requested by the user. + +Let's take a look at the `Conversion `__ class in the standard library: - ``Expr`` @@ -25,8 +24,6 @@ Let us take a look at the ``Conversion`` class in the standard library: - ``ArrayToPointerConversion`` - ``VirtualMemberToFunctionPointerConversion`` -All conversions change the type of an expression. They may be implicit conversions (generated by the compiler) or explicit conversions (requested by the user). - Exploring the subexpressions of an assignment ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -166,7 +163,7 @@ Our starting point for the query is pairs of a base class and a derived class, c where derived.getABaseClass+() = base select base, derived, "The second class is derived from the first." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Note that the transitive closure symbol ``+`` indicates that ``Class.getABaseClass()`` may be followed one or more times, rather than only accepting a direct base class. @@ -178,7 +175,7 @@ A lot of the results are uninteresting template parameters. You can remove those and not exists(base.getATemplateArgument()) and not exists(derived.getATemplateArgument()) -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Finding derived classes with destructors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -197,7 +194,7 @@ Now we can extend the query to find derived classes with destructors, using the and d2 = derived.getDestructor() select base, derived, "The second class is derived from the first, and both have a destructor." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Notice that getting the destructor implicitly asserts that one exists. As a result, this version of the query returns fewer results than before. @@ -217,17 +214,17 @@ Our last change is to use ``Function.isVirtual()`` to find cases where the base and not d1.isVirtual() select d1, "This destructor should probably be virtual." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ That completes the query. -There is a similar built-in LGTM `query `__ that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page. +There is a similar built-in `query `__ on LGTM.com that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page. -What next? ----------- +Further reading +--------------- - Explore other ways of querying classes using examples from the `C/C++ cookbook `__. -- Take a look at the :doc:`Analyzing data flow in C/C++ ` tutorial. -- Try the worked examples in the following topics: :doc:`Example: Checking that constructors initialize all private fields `, and :doc:`Example: Checking for allocations equal to 'strlen(string)' without space for a null terminator `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Take a look at the :doc:`Analyzing data flow in C and C++ ` tutorial. +- Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases `, and :doc:`Detecting a potential buffer overflow `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/dataflow.rst b/docs/language/learn-ql/cpp/dataflow.rst index 686759c049f..2b12986ce94 100644 --- a/docs/language/learn-ql/cpp/dataflow.rst +++ b/docs/language/learn-ql/cpp/dataflow.rst @@ -1,13 +1,12 @@ -Analyzing data flow in C/C++ -============================ +Analyzing data flow in C and C++ +================================ -Overview --------- +You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. -This topic describes how data flow analysis is implemented in the CodeQL libraries for C/C++ and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +About data flow +--------------- -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- @@ -296,12 +295,12 @@ Exercise 3: Write a class that represents flow sources from ``getenv``. (`Answer Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from ``getenv`` to ``gethostbyname``. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- -- Try the worked examples in the following topics: :doc:`Example: Checking that constructors initialize all private fields ` and :doc:`Example: Checking for allocations equal to 'strlen(string)' without space for a null terminator `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Try the worked examples in the following topics: :doc:`Refining a query to account for edge cases ` and :doc:`Detecting a potential buffer overflow `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. Answers ------- diff --git a/docs/language/learn-ql/cpp/expressions-types.rst b/docs/language/learn-ql/cpp/expressions-types.rst index 1595d594683..39da25330d3 100644 --- a/docs/language/learn-ql/cpp/expressions-types.rst +++ b/docs/language/learn-ql/cpp/expressions-types.rst @@ -1,13 +1,10 @@ -Tutorial: Expressions, types and statements -=========================================== +Expressions, types, and statements in C and C++ +=============================================== -Overview --------- +You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments. -This topic contains worked examples of how to write queries using the standard CodeQL library classes for C/C++ expressions, types, and statements. - -Expressions and types ---------------------- +Expressions and types in CodeQL +------------------------------- Each part of an expression in C becomes an instance of the ``Expr`` class. For example, the C code ``x = x + 1`` becomes an ``AssignExpr``, an ``AddExpr``, two instances of ``VariableAccess`` and a ``Literal``. All of these CodeQL classes extend ``Expr``. @@ -24,7 +21,7 @@ In the following example we find instances of ``AssignExpr`` which assign the co where e.getRValue().getValue().toInt() = 0 select e, "Assigning the value 0 to something." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ The ``where`` clause in this example gets the expression on the right side of the assignment, ``getRValue()``, and compares it with zero. Notice that there are no checks to make sure that the right side of the assignment is an integer or that it has a value (that is, it is compile-time constant, rather than a variable). For expressions where either of these assumptions is wrong, the associated predicate simply does not return anything and the ``where`` clause will not produce a result. You could think of it as if there is an implicit ``exists(e.getRValue().getValue().toInt())`` at the beginning of this line. @@ -34,7 +31,7 @@ It is also worth noting that the query above would find this C code: yPtr = NULL; -This is because the database contains a representation of the code base after the preprocessor transforms have run (for more information, see `Database generation `__). This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. +This is because the database contains a representation of the code base after the preprocessor transforms have run. This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. For more information, see `Database generation `__ on LGTM.com. Finding assignments of 0 to an integer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -50,7 +47,7 @@ We can make the query more specific by defining a condition for the left side of and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType select e, "Assigning the value 0 to an integer." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This checks that the left side of the assignment has a type that is some kind of integer. Note the call to ``Type.getUnspecifiedType()``. This resolves ``typedef`` types to their underlying types so that the query finds assignments like this one: @@ -61,8 +58,8 @@ This checks that the left side of the assignment has a type that is some kind of i = 0; -Statements ----------- +Statements in CodeQL +-------------------- We can refine the query further using statements. In this case we use the class ``ForStmt``: @@ -110,7 +107,7 @@ Unfortunately this would not quite work, because the loop initialization is actu and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType select e, "Assigning the value 0 to an integer, inside a for loop initialization." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Finding assignments of 0 within the loop body ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -128,14 +125,14 @@ We can find assignments inside the loop body using similar code with the predica and e.getLValue().getType().getUnderlyingType() instanceof IntegralType select e, "Assigning the value 0 to an integer, inside a for loop body." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Note that we replaced ``e.getEnclosingStmt()`` with ``e.getEnclosingStmt().getParentStmt*()``, to find an assignment expression that is deeply nested inside the loop body. The transitive closure modifier ``*`` here indicates that ``Stmt.getParentStmt()`` may be followed zero or more times, rather than just once, giving us the statement, its parent statement, its parent's parent statement etc. -What next? ----------- +Further reading +--------------- - Explore other ways of finding types and statements using examples from the C/C++ cookbook for `types `__ and `statements `__. -- Take a look at the :doc:`Conversions and classes ` and :doc:`Analyzing data flow in C/C++ ` tutorials. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Take a look at the :doc:`Conversions and classes in C and C++ ` and :doc:`Analyzing data flow in C and C++ ` tutorials. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 51f07a8d0f0..841add0d4b0 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -1,10 +1,12 @@ -Tutorial: Function classes -========================== +Functions in C and C++ +======================= + +You can use CodeQL to explore functions in C and C++ code. Overview -------- -The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`Introducing the C/C++ libraries `). +The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`CodeQL libraries for C and C++ `). The example queries in this topic explore some of the most useful library predicates for querying functions. @@ -26,7 +28,7 @@ This query is very general, so there are probably too many results to be interes Finding functions that are not called ------------------------------------- -It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`Introducing the C/C++ libraries `). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate. +It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`CodeQL libraries for C and C++ `). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate. .. code-block:: ql @@ -36,7 +38,7 @@ It might be more interesting to find functions that are not called, using the st where not exists(FunctionCall fc | fc.getTarget() = f) select f, "This function is never called." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ The new query finds functions that are not the target of any ``FunctionCall``—in other words, functions that are never called. You may be surprised by how many results the query finds. However, if you examine the results, you can see that many of the functions it finds are used indirectly. To create a query that finds only unused functions, we need to refine the query and exclude other ways of using a function. @@ -54,7 +56,7 @@ You can modify the query to remove functions where a function pointer is used to and not exists(FunctionAccess fa | fa.getTarget() = f) select f, "This function is never called, or referenced with a function pointer." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This query returns fewer results. However, if you examine the results then you can probably still find potential refinements. @@ -76,7 +78,7 @@ This query uses ``Function`` and ``FunctionCall`` to find calls to the function and not fc.getArgument(1) instanceof StringLiteral select fc, "sprintf called with variable format string." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ This uses: @@ -87,10 +89,10 @@ Note that we could have used ``Declaration.getName()``, but ``Declaration.getQua The LGTM version of this query is considerably more complicated, but if you look carefully you will find that its structure is the same. See `Non-constant format string `__ and click **Open in query console** at the top of the page. -What next? ----------- +Further reading +--------------- - Explore other ways of finding functions using examples from the `C/C++ cookbook `__. -- Take a look at some of the other tutorials: :doc:`Expressions, types and statements `, :doc:`Conversions and classes `, and :doc:`Analyzing data flow in C/C++ `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Take a look at some other tutorials: :doc:`Expressions, types and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/guards.rst b/docs/language/learn-ql/cpp/guards.rst index f21a7f866e5..409df0a8f81 100644 --- a/docs/language/learn-ql/cpp/guards.rst +++ b/docs/language/learn-ql/cpp/guards.rst @@ -1,8 +1,10 @@ Using the guards library in C and C++ ===================================== -Overview --------- +You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. + +About the guards library +------------------------ The guards library (defined in ``semmle.code.cpp.controlflow.Guards``) provides a class `GuardCondition `__ representing Boolean values that are used to make control flow decisions. A ``GuardCondition`` is considered to guard a basic block if the block can only be reached if the ``GuardCondition`` is evaluated a certain way. For instance, in the following code, ``x < 10`` is a ``GuardCondition``, and it guards all the code before the return statement. @@ -20,7 +22,7 @@ A ``GuardCondition`` is considered to guard a basic block if the block can only The ``controls`` predicate ------------------------------------------------- +-------------------------- The ``controls`` predicate helps determine which blocks are only run when the ``GuardCondition`` evaluates a certain way. ``guard.controls(block, testIsTrue)`` holds if ``block`` is only entered if the value of this condition is ``testIsTrue``. diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 6bea8d40c2c..4960cfc5dba 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -1,10 +1,13 @@ -Introducing the CodeQL libraries for C/C++ -========================================== +CodeQL library for C and C++ +============================ -Overview --------- +When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. -There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: +About the CodeQL library for C and C++ +-------------------------------------- + +There is an extensive library for analyzing CodeQL databases extracted from C/C++ projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. +The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``cpp.qll`` imports all the core C/C++ library modules, so you can include the complete library by beginning your query with: .. code-block:: ql @@ -12,9 +15,7 @@ There is an extensive library for analyzing CodeQL databases extracted from C/C+ The rest of this topic summarizes the available CodeQL classes and corresponding C/C++ constructs. -NOTE: You can find related classes and features using the query console's auto-complete feature. You can also press *F3* to jump to the definition of any element; library files are opened in new tabs in the console. - -Summary of the library classes +Commonly-used library classes ------------------------------ The most commonly used standard library classes are listed below. The listing is broken down by functionality. Each library class is annotated with a C/C++ construct it corresponds to. @@ -31,7 +32,7 @@ This table lists `Declaration `__ | | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | `LocalVariable `__ | | +| ``int`` *func* ``( void ) {`` ... ``float`` *var* ``;`` ... ``}`` | `LocalVariable `__ | See also `Initializer `__ | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``class`` *C* ``{`` ... ``int`` *var* ``;`` ... ``}`` | `MemberVariable `__ | | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -286,6 +287,8 @@ This table lists subclasses of `Expr `__ ``)`` | `NoExceptExpr `__ | | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| `Expr `__ ``=`` `Expr `__ | `AssignExpr `__ | See also `Initializer `__ | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | `Expr `__ ``+=`` `Expr `__ | | `AssignAddExpr `__ | | | | | `AssignPointerAddExpr `__ | | +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -519,9 +522,9 @@ This table lists `Preprocessor `, :doc:`Expressions, types and statements `, :doc:`Conversions and classes `, and :doc:`Analyzing data flow in C/C++ `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Experiment with the worked examples in the CodeQL for C/C++ topics: :doc:`Functions in C and C++ `, :doc:`Expressions, types, and statements in C and C++ `, :doc:`Conversions and classes in C and C++ `, and :doc:`Analyzing data flow in C and C++ `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/private-field-initialization.rst b/docs/language/learn-ql/cpp/private-field-initialization.rst index 26b57660142..c1f9224a145 100644 --- a/docs/language/learn-ql/cpp/private-field-initialization.rst +++ b/docs/language/learn-ql/cpp/private-field-initialization.rst @@ -1,13 +1,15 @@ -Example: Checking that constructors initialize all private fields -================================================================= +Refining a query to account for edge cases +========================================== + +You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases. Overview -------- -This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C/C++ `. +This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C and C++ `. -Problem—finding every private field and checking for initialization -------------------------------------------------------------------- +Finding every private field and checking for initialization +----------------------------------------------------------- Writing a query to check if a constructor initializes all private fields seems like a simple problem, but there are several edge cases to account for. @@ -100,7 +102,7 @@ You may also wish to consider methods called by constructors that assign to the int m_value; }; -This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls (see `Recursion `__ for more information). +This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see `Recursion `__ in the QL language reference. .. code-block:: ql @@ -124,7 +126,7 @@ This case can be excluded by creating a recursive predicate. The recursive predi Refinement 4—simplifying the query ---------------------------------- -Finally we can simplify the query by using the `transitive closure operator `__. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. +Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see `Transitive closures `__ in the QL language reference. .. code-block:: ql @@ -142,11 +144,11 @@ Finally we can simplify the query by using the `transitive closure operator `__ +➤ `See this in the query console on LGTM.com `__ -What next? ----------- +Further reading +--------------- -- Take a look at another example: :doc:`Checking for allocations equal to 'strlen(string)' without space for a null terminator `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Take a look at another example: :doc:`Detecting a potential buffer overflow `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/cpp/ql-for-cpp.rst b/docs/language/learn-ql/cpp/ql-for-cpp.rst index b1596c7de92..bd52291a7f8 100644 --- a/docs/language/learn-ql/cpp/ql-for-cpp.rst +++ b/docs/language/learn-ql/cpp/ql-for-cpp.rst @@ -1,8 +1,9 @@ -CodeQL for C/C++ -================ +CodeQL for C and C++ +==================== + +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C and C++ codebases. .. toctree:: - :glob: :hidden: introduce-libraries-cpp @@ -12,47 +13,36 @@ CodeQL for C/C++ dataflow private-field-initialization zero-space-terminator - -These topics provide an overview of the CodeQL libraries for C/C++ and show examples of how to write queries that use them. - -- `Basic C/C++ query `__ describes how to write and run queries using LGTM. - -- :doc:`Introducing the CodeQL libraries for C/C++ ` introduces the standard libraries used to write queries for C and C++ code. - -- :doc:`Tutorial: Function classes ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ functions. - -- :doc:`Tutorial: Expressions, types and statements ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ expressions, types and statements. - -- :doc:`Tutorial: Conversions and classes ` demonstrates how to write queries using the standard CodeQL library classes for C/C++ conversions and classes. - -- :doc:`Tutorial: Analyzing data flow in C/C++ ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C/C++. - -- :doc:`Example: Checking that constructors initialize all private fields ` works through the development of a query. It introduces recursive predicates and shows the typical workflow used to refine a query. - -- :doc:`Example: Checking for allocations equal to strlen(string) without space for a null terminator ` shows how a query to detect this particular buffer issue was developed. - -Advanced libraries ----------------------------------- - -.. toctree:: - :hidden: - guards range-analysis value-numbering-hash-cons -- :doc:`Using the guards library in C and C++ ` demonstrates how to identify conditional expressions that control the execution of other code and what guarantees they provide. -- :doc:`Using range analysis for C and C++ ` demonstrates how to determine constant upper and lower bounds and possible overflow or underflow of expressions. +- `Basic C/C++ query `__: Learn to write and run a simple CodeQL query using LGTM. -- :doc:`Using hash consing and value numbering for C and C++ ` demonstrates how to recognize expressions that are syntactically identical or compute the same value at runtime. +- :doc:`CodeQL library for C and C++ `: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++. +- :doc:`Functions in C and C++ `: You can use CodeQL to explore functions in C and C++ code. -Other resources +- :doc:`Expressions, types, and statements in C and C++ `: You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments. + +- :doc:`Conversions and classes in C and C++ `: You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed. + +- :doc:`Analyzing data flow in C and C++ `: You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. + +- :doc:`Refining a query to account for edge cases `: You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases. + +- :doc:`Detecting a potential buffer overflow `: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. + +- :doc:`Using the guards library in C and C++ `: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases. + +- :doc:`Using range analysis for C and C++ `: You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. + +- :doc:`Hash consing and value numbering `: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. + +Further reading --------------- -.. TODO: Rename the cookbooks: C/C++ cookbook, or C/C++ CodeQL cookbook, or CodeQL cookbook for C/C++, or...? - - For examples of how to query common C/C++ elements, see the `C/C++ cookbook `__. - For the queries used in LGTM, display a `C/C++ query `__ and click **Open in query console** to see the code used to find alerts. - For more information about the library for C/C++ see the `CodeQL library for C/C++ `__. diff --git a/docs/language/learn-ql/cpp/range-analysis.rst b/docs/language/learn-ql/cpp/range-analysis.rst index c60465e131d..ba324e86ac9 100644 --- a/docs/language/learn-ql/cpp/range-analysis.rst +++ b/docs/language/learn-ql/cpp/range-analysis.rst @@ -1,10 +1,10 @@ Using range analysis for C and C++ ================================== -Overview --------- +You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow. -Range analysis determines upper and lower bounds for an expression. +About the range analysis library +-------------------------------- The range analysis library (defined in ``semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis``) provides a set of predicates for determining constant upper and lower bounds on expressions, as well as recognizing integer overflows. For performance, the library performs automatic widening and therefore may not provide the tightest possible bounds. diff --git a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst index e05f93dbae1..de102a15f6d 100644 --- a/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst +++ b/docs/language/learn-ql/cpp/value-numbering-hash-cons.rst @@ -1,15 +1,14 @@ Hash consing and value numbering -================================================= +================================ -Overview --------- +You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases. + +About the hash consing and value numbering libraries +---------------------------------------------------- In C and C++ databases, each node in the abstract syntax tree is represented by a separate object. This allows both analysis and results display to refer to specific appearances of a piece of syntax. However, it is frequently useful to determine whether two expressions are equivalent, either syntactically or semantically. -The `hash consing `__ library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The `global value numbering `__ library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. - -Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. - +The hash consing library (defined in ``semmle.code.cpp.valuenumbering.HashCons``) provides a mechanism for identifying expressions that have the same syntactic structure. The global value numbering library (defined in ``semmle.code.cpp.valuenumbering.GlobalValueNumbering``) provides a mechanism for identifying expressions that compute the same value at runtime. Both libraries partition the expressions in each function into equivalence classes represented by objects. Each ``HashCons`` object represents a set of expressions with identical parse trees, while ``GVN`` objects represent sets of expressions that will always compute the same value. For more information, see `Hash consing `__ and `Value numbering `__ on Wikipedia. Example C code -------------- @@ -111,4 +110,3 @@ Example query hashCons(outer.getCondition()) = hashCons(inner.getCondition()) select inner.getCondition(), "The condition of this if statement duplicates the condition of $@", outer.getCondition(), "an enclosing if statement" - diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index a9370f7828d..a25437865f7 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -1,10 +1,7 @@ -Example: Checking for allocations equal to ``strlen(string)`` without space for a null terminator -================================================================================================= +Detecting a potential buffer overflow +===================================== -Overview --------- - -This topic describes how a C/C++ query for detecting a potential buffer overflow was developed. For a full overview of the topics available for learning to write queries for C/C++ code, see :doc:`CodeQL for C/C++ `. +You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++. This topic describes how a C/C++ query for detecting a potential buffer overflow was developed. Problem—detecting memory allocation that omits space for a null termination character ------------------------------------------------------------------------------------- @@ -98,7 +95,7 @@ When you have defined the basic query then you can refine the query to include f Improving the query using the 'SSA' library ------------------------------------------- -The ``SSA`` library represents variables in `static single assignment `__ (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. +The ``SSA`` library represents variables in static single assignment (SSA) form. In this form, each variable is assigned exactly once and every variable is defined before it is used. The use of SSA variables simplifies queries considerably as much of the local data flow analysis has been done for us. For more information, see `Static single assignment `__ on Wikipedia. Including examples where the string size is stored before use ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -224,8 +221,8 @@ The completed query will now identify cases where the result of ``strlen`` is st where malloc.getAllocatedSize() instanceof StrlenCall select malloc, "This allocation does not include space to null-terminate the string." -What next? ----------- +Further reading +--------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/dataflow.rst b/docs/language/learn-ql/csharp/dataflow.rst index 3b9bb69d7da..c4b597428df 100644 --- a/docs/language/learn-ql/csharp/dataflow.rst +++ b/docs/language/learn-ql/csharp/dataflow.rst @@ -1,13 +1,14 @@ Analyzing data flow in C# ========================= -Overview --------- +You can use CodeQL to track the flow of data through a C# program to its use. -This topic describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +About this article +------------------ -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries. +The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- @@ -17,7 +18,7 @@ Local data flow is data flow within a single method or callable. Local data flow Using local data flow ~~~~~~~~~~~~~~~~~~~~~ -The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). It is possible to map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: +The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). You can map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: .. code-block:: ql @@ -45,9 +46,9 @@ or using the predicates ``exprNode`` and ``parameterNode``: */ ParameterNode parameterNode(Parameter p) { ... } -The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localFlow``. +The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localFlow``. -For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -65,9 +66,9 @@ Local taint tracking extends local data flow by including non-value-preserving f If ``x`` is a tainted string then ``y`` is also tainted. -The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localTaint``. +The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``. -For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -76,7 +77,7 @@ For example, finding taint propagation from a parameter ``source`` to an express Examples ~~~~~~~~ -The following query finds the filename passed to ``System.IO.File.Open``: +This query finds the filename passed to ``System.IO.File.Open``: .. code-block:: ql @@ -99,7 +100,7 @@ Unfortunately this will only give the expression in the argument, not the values and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0))) select src -Then we can make the source more specific, for example an access to a public parameter. The following query finds where a public parameter is used to open a file: +Then we can make the source more specific, for example an access to a public parameter. This query finds instances where a public parameter is used to open a file: .. code-block:: ql @@ -112,7 +113,7 @@ Then we can make the source more specific, for example an access to a public par and call.getEnclosingCallable().(Member).isPublic() select p, "Opening a file from a public method." -The following example finds calls to ``String.Format`` where the format string isn't hard-coded: +This query finds calls to ``String.Format`` where the format string isn't hard-coded: .. code-block:: ql @@ -139,7 +140,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ -The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows: +The global data flow library is used by extending the class ``DataFlow::Configuration``: .. code-block:: ql @@ -157,12 +158,12 @@ The global data flow library is used by extending the class ``DataFlow::Configur } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: -- ``isSource`` - defines where data may flow from -- ``isSink`` - defines where data may flow to -- ``isBarrier`` - optionally, restricts the data flow -- ``isAdditionalFlowStep`` - optionally, adds additional flow steps +- ``isSource`` - defines where data may flow from. +- ``isSink`` - defines where data may flow to. +- ``isBarrier`` - optionally, restricts the data flow. +- ``isAdditionalFlowStep`` - optionally, adds additional flow steps. The characteristic predicate (``MyDataFlowConfiguration()``) defines the name of the configuration, so ``"..."`` must be replaced with a unique name. @@ -177,7 +178,7 @@ The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node Using global taint tracking ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Global taint tracking is to global data flow what local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows: +Global taint tracking is to global data flow what local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration``: .. code-block:: ql @@ -195,12 +196,12 @@ Global taint tracking is to global data flow what local taint tracking is to loc } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: -- ``isSource`` - defines where taint may flow from -- ``isSink`` - defines where taint may flow to -- ``isSanitizer`` - optionally, restricts the taint flow -- ``isAdditionalTaintStep`` - optionally, adds additional taint steps +- ``isSource`` - defines where taint may flow from. +- ``isSink`` - defines where taint may flow to. +- ``isSanitizer`` - optionally, restricts the taint flow. +- ``isAdditionalTaintStep`` - optionally, adds additional taint steps. Similar to global data flow, the characteristic predicate (``MyTaintTrackingConfiguration()``) defines the unique name of the configuration and the taint analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``. @@ -214,7 +215,7 @@ The class ``RemoteSourceFlow`` (defined in module ``semmle.code.csharp.dataflow. Example ~~~~~~~ -The following example shows a data flow configuration that uses all public API parameters as data sources. +This query shows a data flow configuration that uses all public API parameters as data sources: .. code-block:: ql @@ -236,30 +237,30 @@ The following example shows a data flow configuration that uses all public API p Class hierarchy ~~~~~~~~~~~~~~~ -- ``DataFlow::Configuration`` - base class for custom global data flow analysis -- ``DataFlow::Node`` - an element behaving as a data flow node +- ``DataFlow::Configuration`` - base class for custom global data flow analysis. +- ``DataFlow::Node`` - an element behaving as a data flow node. - - ``DataFlow::ExprNode`` - an expression behaving as a data flow node - - ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry + - ``DataFlow::ExprNode`` - an expression behaving as a data flow node. + - ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry. - - ``PublicCallableParameter`` - a parameter to a public method/callable in a public class + - ``PublicCallableParameter`` - a parameter to a public method/callable in a public class. - - ``RemoteSourceFlow`` - data flow from network/remote input + - ``RemoteSourceFlow`` - data flow from network/remote input. - - ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input + - ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input. - - ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest`` - - ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox`` + - ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest``. + - ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox``. - - ``WcfRemoteFlowSource`` - data flow from a WCF web service - - ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service + - ``WcfRemoteFlowSource`` - data flow from a WCF web service. + - ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service. -- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis +- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis. Examples ~~~~~~~~ -The following data flow configuration tracks data flow from environment variables to opening files: +This data flow configuration tracks data flow from environment variables to opening files: .. code-block:: ql @@ -300,7 +301,7 @@ Exercise 4: Using the answers from 2 and 3, write a query to find all global dat Extending library data flow --------------------------- -*Library* data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries. +Library data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries. To define new library data flow, extend the class ``LibraryTypeDataFlow`` from the module ``semmle.code.csharp.dataflow.LibraryTypeDataFlow``. Override the predicate ``callableFlow`` to define how data flows through the methods in the class. ``callableFlow`` has the signature @@ -308,9 +309,9 @@ To define new library data flow, extend the class ``LibraryTypeDataFlow`` from t predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable callable, boolean preservesValue) -- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow -- ``source`` - the data flow input -- ``sink`` - the data flow output +- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow. +- ``source`` - the data flow input. +- ``sink`` - the data flow output. - ``preservesValue`` - whether the flow step preserves the value, for example if ``x`` is a string then ``x.ToString()`` preserves the value where as ``x.ToLower()`` does not. Class hierarchy @@ -318,24 +319,24 @@ Class hierarchy - ``Callable`` - a callable (methods, accessors, constructors etc.) - - ``SourceDeclarationCallable`` - an unconstructed callable + - ``SourceDeclarationCallable`` - an unconstructed callable. -- ``CallableFlowSource`` - the input of data flow into the callable +- ``CallableFlowSource`` - the input of data flow into the callable. - - ``CallableFlowSourceQualifier`` - the data flow comes from the object itself - - ``CallableFlowSourceArg`` - the data flow comes from an argument to the call + - ``CallableFlowSourceQualifier`` - the data flow comes from the object itself. + - ``CallableFlowSourceArg`` - the data flow comes from an argument to the call. -- ``CallableFlowSink`` - the output of data flow from the callable +- ``CallableFlowSink`` - the output of data flow from the callable. - - ``CallableFlowSinkQualifier`` - the output is to the object itself - - ``CallableFlowSinkReturn`` - the output is returned from the call - - ``CallableFlowSinkArg`` - the output is an argument - - ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ) + - ``CallableFlowSinkQualifier`` - the output is to the object itself. + - ``CallableFlowSinkReturn`` - the output is returned from the call. + - ``CallableFlowSinkArg`` - the output is an argument. + - ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ). Example ~~~~~~~ -The following example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``. +This example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``. .. code-block:: ql @@ -489,7 +490,7 @@ Exercise 4 Exercise 5 ~~~~~~~~~~ -All properties can flow data. We can declare this as follows: +All properties can flow data: .. code-block:: ql @@ -545,9 +546,9 @@ This can be adapted from the ``SystemUriFlow`` class: } } -What next? ----------- +Further reading +--------------- - Learn about the standard libraries used to write queries for C# in :doc:`Introducing the C# libraries `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst index 32a782d5034..f262478dc44 100644 --- a/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst +++ b/docs/language/learn-ql/csharp/introduce-libraries-csharp.rst @@ -1,18 +1,20 @@ -Introducing the CodeQL libraries for C# -======================================= +CodeQL library for C# +===================== -Overview --------- +When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#. -There is an extensive library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with: +About the CodeQL libraries for C# +--------------------------------- + +There is an extensive core library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with: .. code-block:: ql import csharp -Since this is required for all C# queries, it is omitted from code snippets below. +Since this is required for all C# queries, it's omitted from code snippets below. -The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. See :doc:`CodeQL for C# ` for information about these additional libraries. +The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. For information about these additional libraries, see :doc:`CodeQL for C# `. Class hierarchies ~~~~~~~~~~~~~~~~~ @@ -42,7 +44,7 @@ Each section contains a class hierarchy, showing the inheritance structure betwe - ``AddExpr``, ``SubExpr``, ``MulExpr``, ``DivExpr``, ``RemExpr`` -This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, then use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, then use the class ``AddExpr``. +This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, use the class ``AddExpr``. Classes can also be considered to be *sets*, and the ``extends`` relation between classes defines a subset. Every member of class ``AddExpr`` is also in the class ``BinaryArithmeticOperation``. In general, classes overlap and an entity can be a member of several classes. @@ -50,14 +52,14 @@ This overview omits some of the less important or intermediate classes from the Each class has predicates, which are logical propositions about that class. They also define navigable relationships between classes. Predicates are inherited, so for example the ``AddExpr`` class inherits the predicates ``getLeftOperand()`` and ``getRightOperand()`` from ``BinaryArithmeticOperation``, and ``getType()`` from class ``Expr``. This is similar to how methods are inherited in object-oriented programming languages. -In this overview, we present the most common and useful predicates. Consult the `reference `__, the CodeQL source code, and autocomplete in the editor for the complete list of predicates available on each class. +In this overview, we present the most common and useful predicates. For the complete list of predicates available on each class, you can look in the CodeQL source code, use autocomplete in the editor, or see the `C# reference `__. Exercises ~~~~~~~~~ Each section in this topic contains exercises to check your understanding. -Exercise 1: Simplify the following query: +Exercise 1: Simplify this query: .. code-block:: ql @@ -84,11 +86,11 @@ Class hierarchy Predicates ~~~~~~~~~~ -- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``) -- ``getNumberOfLines()`` - gets the number of lines (for source files only) -- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``) -- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``) -- ``getParent()`` - gets the parent directory +- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``). +- ``getNumberOfLines()`` - gets the number of lines (for source files only). +- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``). +- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``). +- ``getParent()`` - gets the parent directory. Examples ~~~~~~~~ @@ -116,7 +118,7 @@ Exercise 2: Write a query to find the source file with the largest number of lin Elements -------- -The class `Element `__ is the base class for all parts of a C# program, and it is the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. +The class `Element `__ is the base class for all parts of a C# program, and it's the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class. ``Element`` forms a hierarchical structure of the program, which can be navigated using the ``getParent()`` and ``getChild()`` predicates. This is much like an abstract syntax tree, and also applies to elements in assemblies. @@ -125,10 +127,10 @@ Predicates The ``Element`` class provides common functionality for all program elements, including: -- ``getLocation()`` - gets the text span in the source code -- ``getFile()`` - gets the ``File`` containing the ``Element`` -- ``getParent()`` - gets the parent ``Element``, if any -- ``getAChild()`` - gets a child ``Element`` of this element, if any +- ``getLocation()`` - gets the text span in the source code. +- ``getFile()`` - gets the ``File`` containing the ``Element``. +- ``getParent()`` - gets the parent ``Element``, if any. +- ``getAChild()`` - gets a child ``Element`` of this element, if any. Examples ~~~~~~~~ @@ -163,11 +165,11 @@ Predicates Some predicates of ``Location`` include: -- ``getFile()`` - gets the ``File`` -- ``getStartLine()`` - gets the first line of the text -- ``getEndLine()`` - gets the last line of the text -- ``getStartColumn()`` - gets the column of the start of the text -- ``getEndColumn()`` - gets the column of the end of the text +- ``getFile()`` - gets the ``File``. +- ``getStartLine()`` - gets the first line of the text. +- ``getEndLine()`` - gets the last line of the text. +- ``getStartColumn()`` - gets the column of the start of the text. +- ``getEndColumn()`` - gets the column of the end of the text. Examples ~~~~~~~~ @@ -213,10 +215,10 @@ Predicates Useful member predicates on ``Declaration`` include: -- ``getDeclaringType()`` - gets the type containing the declaration, if any -- ``getName()``/``hasName(string)`` - gets the name of the declared entity -- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method -- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration +- ``getDeclaringType()`` - gets the type containing the declaration, if any. +- ``getName()``/``hasName(string)`` - gets the name of the declared entity. +- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method. +- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration. Examples ~~~~~~~~ @@ -262,10 +264,10 @@ Predicates Some common predicates on ``Variable`` are: -- ``getType()`` - gets the ``Type`` of this variable -- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any -- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any -- ``getInitializer()`` - gets the expression used to initialize the variable, if any +- ``getType()`` - gets the ``Type`` of this variable. +- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any. +- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any. +- ``getInitializer()`` - gets the expression used to initialize the variable, if any. Examples ~~~~~~~~ @@ -309,7 +311,7 @@ Class hierarchy - ``VoidType`` - ``void`` - ``PointerType`` - a pointer type -The ``ValueType`` class extends further as follows: +The ``ValueType`` class extends further: - ``ValueType`` - a value type @@ -345,7 +347,7 @@ The ``ValueType`` class extends further as follows: - ``NullableType`` - ``ArrayType`` -The ``RefType`` class extends further as follows: +The ``RefType`` class extends further: - ``RefType`` @@ -369,19 +371,19 @@ Predicates Useful members of ``ValueOrRefType`` include: -- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``) -- ``getABaseInterface()`` - gets an immediate interface of this type, if any -- ``getABaseType()`` - gets an immediate base class or interface of this type, if any -- ``getBaseClass()`` - gets the immediate base class of this type, if any -- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any -- ``getAMember()`` - gets any member (field/method/property etc), if any -- ``getAMethod()`` - gets a method, if any -- ``getAProperty()`` - gets a property, if any -- ``getAnIndexer()`` - gets an indexer, if any -- ``getAnEvent()`` - gets an event, if any -- ``getAnOperator()`` - gets an operator, if any -- ``getANestedType()`` - gets a nested type -- ``getNamespace()`` - gets the enclosing namespace +- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``). +- ``getABaseInterface()`` - gets an immediate interface of this type, if any. +- ``getABaseType()`` - gets an immediate base class or interface of this type, if any. +- ``getBaseClass()`` - gets the immediate base class of this type, if any. +- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any. +- ``getAMember()`` - gets any member (field/method/property etc), if any. +- ``getAMethod()`` - gets a method, if any. +- ``getAProperty()`` - gets a property, if any. +- ``getAnIndexer()`` - gets an indexer, if any. +- ``getAnEvent()`` - gets an event, if any. +- ``getAnOperator()`` - gets an operator, if any. +- ``getANestedType()`` - gets a nested type. +- ``getNamespace()`` - gets the enclosing namespace. Examples ~~~~~~~~ @@ -492,12 +494,12 @@ Predicates Here are a few useful predicates on the ``Callable`` class: -- ``getParameter(int)``/``getAParameter()`` - gets a parameter -- ``calls(Callable)`` - whether there's a direct call from one callable to another -- ``getReturnType()`` - gets the return type -- ``getBody()``/``getExpressionBody()`` - gets the body of the callable +- ``getParameter(int)``/``getAParameter()`` - gets a parameter. +- ``calls(Callable)`` - whether there's a direct call from one callable to another. +- ``getReturnType()`` - gets the return type. +- ``getBody()``/``getExpressionBody()`` - gets the body of the callable. -Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as +Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as: - ``getName()``/``hasName(string)`` - ``getSourceDeclaration()`` @@ -506,10 +508,10 @@ Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declar Methods have additional predicates, including: -- ``getAnOverridee()`` - gets a method that is immediately overridden by this method -- ``getAnOverrider()`` - gets a method that immediately overrides this method -- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method -- ``getAnImplementor()`` - gets a method that immediately implements this interface method +- ``getAnOverridee()`` - gets a method that is immediately overridden by this method. +- ``getAnOverrider()`` - gets a method that immediately overrides this method. +- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method. +- ``getAnImplementor()`` - gets a method that immediately implements this interface method. Examples ~~~~~~~~ @@ -665,7 +667,7 @@ Find an ``if`` statement with a constant condition: where ifStmt.getCondition().hasValue() select ifStmt, "This 'if' statement is constant." -Find an ``if`` statement with an empty "then" clause: +Find an ``if`` statement with an empty "then" block: .. code-block:: ql @@ -680,7 +682,7 @@ Exercises Exercise 6: Write a query to list all empty methods. (`Answer <#exercise-6>`__) -Exercise 7: Modify the last example to also detect empty statements (``;``) in the then block. (`Answer <#exercise-7>`__) +Exercise 7: Modify the last example to also detect empty statements (``;``) in the "then" block. (`Answer <#exercise-7>`__) Exercise 8: Modify the last example to exclude chains of ``if`` statements, where the ``else`` part is another ``if`` statement. (`Answer <#exercise-8>`__) @@ -874,13 +876,13 @@ Predicates Useful predicates on ``Expr`` include: -- ``getType()`` - gets the ``Type`` of the expression -- ``getValue()`` - gets the compile-time constant, if any -- ``hasValue()`` - whether the expression has a compile-time constant -- ``getEnclosingStmt()`` - gets the statement containing the expression, if any -- ``getEnclosingCallable()`` - gets the callable containing the expression, if any -- ``stripCasts()`` - remove all explicit or implicit casts -- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``) +- ``getType()`` - gets the ``Type`` of the expression. +- ``getValue()`` - gets the compile-time constant, if any. +- ``hasValue()`` - whether the expression has a compile-time constant. +- ``getEnclosingStmt()`` - gets the statement containing the expression, if any. +- ``getEnclosingCallable()`` - gets the callable containing the expression, if any. +- ``stripCasts()`` - remove all explicit or implicit casts. +- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``). Examples ~~~~~~~~ @@ -922,7 +924,7 @@ Attributes C# attributes are represented by the class `Attribute `__. They can be present on many C# elements, such as classes, methods, fields, and parameters. The database contains attributes from the source code and all assembly references. -The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. The following two query fragments are identical: +The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. These two query fragments are identical: .. code-block:: ql @@ -939,8 +941,8 @@ Class hierarchy Predicates ~~~~~~~~~~ -- ``getTarget()`` - gets the ``Element`` to which this attribute applies -- ``getArgument(int)`` - gets the given argument of the attribute +- ``getTarget()`` - gets the ``Element`` to which this attribute applies. +- ``getArgument(int)`` - gets the given argument of the attribute. - ``getType()`` - gets the type of this attribute. Note that the class name must end in ``"Attribute"``. Examples @@ -1117,9 +1119,9 @@ Here is the fixed version: else reason = "(not given)" select e, "This is obsolete because " + reason -What next? ----------- +Further reading +--------------- -- Visit :doc:`Tutorial: Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. \ No newline at end of file +- Visit :doc:`Analyzing data flow in C# ` to learn more about writing queries using the standard data flow and taint tracking libraries. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index bc5cc9e9959..6eb3567e808 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -1,27 +1,21 @@ CodeQL for C# ============= +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C# codebases. + .. toctree:: - :glob: :hidden: introduce-libraries-csharp dataflow -These topics provide an overview of the CodeQL libraries for C# and show examples of how to use them. +- `Basic C# query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic C# query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for C# `: When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#. -- :doc:`Introducing the CodeQL libraries for C# ` introduces the standard libraries used to write queries for C# code. +- :doc:`Analyzing data flow in C# `: You can use CodeQL to track the flow of data through a C# program to its use. -.. raw:: html - - - -- :doc:`Tutorial: Analyzing data flow in C# ` demonstrates how to write queries using the standard data flow and taint tracking libraries for C#. - - -Other resources +Further reading --------------- - For examples of how to query common C# elements, see the `C# cookbook `__. diff --git a/docs/language/learn-ql/database.rst b/docs/language/learn-ql/database.rst index fe8e2e273ef..369b1d73fb0 100644 --- a/docs/language/learn-ql/database.rst +++ b/docs/language/learn-ql/database.rst @@ -1,7 +1,7 @@ What's in a CodeQL database? ============================ -A CodeQL database contains a variety of data related to a particular code base at a particular point in time. For details of how the database is generated see `Database generation `__. +A CodeQL database contains a variety of data related to a particular code base at a particular point in time. For details of how the database is generated see `Database generation `__ on LGTM.com. The database contains a full, hierarchical representation of the program defined by the code base. The database schema varies according to the language analyzed. The schema provides an interface between the initial lexical analysis during the extraction process, and the actual complex analysis using CodeQL. When the source code languages being analyzed change (such as Java 7 evolving into Java 8), this interface between the analysis phases can also change. diff --git a/docs/language/learn-ql/go/ast.dot b/docs/language/learn-ql/go/ast.dot new file mode 100644 index 00000000000..fbf32b744ed --- /dev/null +++ b/docs/language/learn-ql/go/ast.dot @@ -0,0 +1,22 @@ +digraph ast { + graph [dpi=300]; + "x" [shape=rect]; + "y" [shape=rect]; + "x + y" [shape=rect]; + "(x + y)" [shape=rect]; + "z" [shape=rect]; + "(x + y) * z" [shape=rect]; + invis1 [style=invis]; + invis2 [style=invis]; + invis3 [style=invis]; + + "(x + y) * z" -> "(x + y)" [label=" 0"]; + "(x + y) * z" -> "z" [label=" 1"]; + "(x + y)" -> "x + y" [label=" 0"]; + "x + y" -> "x" [label=" 0"]; + "x + y" -> "y" [label=" 1"]; + + "z" -> invis1 [style=invis]; + invis1 -> invis2 [style=invis]; + invis1 -> invis3 [style=invis]; +} diff --git a/docs/language/learn-ql/go/ast.png b/docs/language/learn-ql/go/ast.png new file mode 100644 index 00000000000..61a9f29b80a Binary files /dev/null and b/docs/language/learn-ql/go/ast.png differ diff --git a/docs/language/learn-ql/go/cfg.dot b/docs/language/learn-ql/go/cfg.dot new file mode 100644 index 00000000000..47db3df4c57 --- /dev/null +++ b/docs/language/learn-ql/go/cfg.dot @@ -0,0 +1,8 @@ +digraph cfg { + graph [dpi=300]; + rankdir=LR; + "x := 0" -> "p != nil"; + "p != nil" -> "x = p.f"; + "p != nil" -> "return x"; + "x = p.f" -> "return x"; +} diff --git a/docs/language/learn-ql/go/cfg.png b/docs/language/learn-ql/go/cfg.png new file mode 100644 index 00000000000..1290dadb870 Binary files /dev/null and b/docs/language/learn-ql/go/cfg.png differ diff --git a/docs/language/learn-ql/go/cfg2.dot b/docs/language/learn-ql/go/cfg2.dot new file mode 100644 index 00000000000..b8dcd71ee25 --- /dev/null +++ b/docs/language/learn-ql/go/cfg2.dot @@ -0,0 +1,14 @@ +digraph cfg2 { + graph [dpi=300]; + rankdir=LR; + + "p != nil is true" [shape=box]; + "p != nil is false" [shape=box]; + + "x := 0" -> "p != nil"; + "p != nil" -> "p != nil is true"; + "p != nil is true" -> "x = p.f"; + "p != nil" -> "p != nil is false"; + "p != nil is false" -> "return x"; + "x = p.f" -> "return x"; +} diff --git a/docs/language/learn-ql/go/cfg2.png b/docs/language/learn-ql/go/cfg2.png new file mode 100644 index 00000000000..617fe4fe4dc Binary files /dev/null and b/docs/language/learn-ql/go/cfg2.png differ diff --git a/docs/language/learn-ql/go/dfg.dot b/docs/language/learn-ql/go/dfg.dot new file mode 100644 index 00000000000..82253c9b133 --- /dev/null +++ b/docs/language/learn-ql/go/dfg.dot @@ -0,0 +1,11 @@ +digraph dfg { + graph [dpi=300]; + rankdir=LR; + + "x" [shape=diamond]; + "return x" [label=x>]; + + "0" -> "x"; + "p.f" -> "x"; + "x" -> "return x"; +} diff --git a/docs/language/learn-ql/go/dfg.png b/docs/language/learn-ql/go/dfg.png new file mode 100644 index 00000000000..6727af7b4ac Binary files /dev/null and b/docs/language/learn-ql/go/dfg.png differ diff --git a/docs/language/learn-ql/go/introduce-libraries-go.rst b/docs/language/learn-ql/go/introduce-libraries-go.rst new file mode 100644 index 00000000000..e47ce2b94c4 --- /dev/null +++ b/docs/language/learn-ql/go/introduce-libraries-go.rst @@ -0,0 +1,621 @@ +CodeQL library for Go +===================== + +When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go. + +Overview +-------- + +CodeQL ships with an extensive library for analyzing Go code. The classes in this library present +the data from a CodeQL database in an object-oriented form and provide abstractions and predicates +to help you with common analysis tasks. + +The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The +module ``go.qll`` imports most other standard library modules, so you can include the complete +library by beginning your query with: + +.. code-block:: ql + + import go + +Broadly speaking, the CodeQL library for Go provides two views of a Go code base: at the `syntactic +level`, source code is represented as an `abstract syntax tree +`__ (AST), while at the `data-flow level` it is +represented as a `data-flow graph `__ (DFG). In +between, there is also an intermediate representation of the program as a control-flow graph (CFG), +though this representation is rarely useful on its own and mostly used to construct the higher-level +DFG representation. + +The AST representation captures the syntactic structure of the program. You can use it to reason +about syntactic properties such as the nesting of statements within each other, but also about the +types of expressions and which variable a name refers to. + +The DFG, on the other hand, provides an approximation of how data flows through variables and +operations at runtime. It is used, for example, by the security queries to model the way +user-controlled input can propagate through the program. Additionally, the DFG contains information +about which function may be invoked by a given call (taking virtual dispatch through interfaces into +account), as well as control-flow information about the order in which different operations may be +executed at runtime. + +As a rule of thumb, you normally want to use the AST only for superficial syntactic queries. Any +analysis involving deeper semantic properties of the program should be done on the DFG. + +The rest of this tutorial briefly summarizes the most important classes and predicates provided by +this library, including references to the `detailed API documentation +`__ where applicable. We start by giving an overview of the AST +representation, followed by an explanation of names and entities, which are used to represent +name-binding information, and of types and type information. Then we move on to control flow and the +data-flow graph, and finally the call graph and a few advanced topics. + +Abstract syntax +--------------- + +The AST presents the program as a hierarchical structure of nodes, each of which corresponds to a +syntactic element of the program source text. For example, there is an AST node for each expression +and each statement in the program. These AST nodes are arranged into a parent-child relationship +reflecting the nesting of syntactic elements and the order in which inner elements appear in +enclosing ones. + +For example, this is the AST for the expression ``(x + y) * z``: + +|ast| + +It is composed of six AST nodes, representing ``x``, ``y``, ``x + y``, ``(x + y)``, ``z`` and the +entire expression ``(x + y) * z``, respectively. The AST nodes representing ``x`` and ``y`` are +children of the AST node representing ``x + y``, ``x`` being the zeroth child and ``y`` being the +first child, reflecting their order in the program text. Similarly, ``x + y`` is the only child of +``(x + y)``, which is the zeroth child of ``(x + y) * z``, whose first child is ``z``. + +All AST nodes belong to class `AstNode +`__, which defines generic +tree traversal predicates: + +- ``getChild(i)``: returns the ``i``\ th child of this AST node. +- ``getAChild()``: returns any child of this AST node. +- ``getParent()``: returns the parent node of this AST node, if any. + +These predicates should only be used to perform generic AST traversal. To access children of +specific AST node types, the specialized predicates introduced below should be used instead. In +particular, queries should not rely on the numeric indices of child nodes relative to their parent +nodes: these are considered an implementation detail that may change between versions of the +library. + +The predicate ``toString()`` in class ``AstNode`` nodes gives a short description of the AST node, +usually just indicating what kind of node it is. The ``toString()`` predicate does `not` provide +access to the source text corresponding to an AST node. The source text is not stored in the +dataset, and hence is not directly accessible to CodeQL queries. + +The predicate ``getLocation()`` in class ``AstNode`` returns a `Location +`__ entity +describing the source location of the program element represented by the AST node. You can use its +member predicates ``getFile()``, ``getStartLine()``, ``getStartColumn``, ``getEndLine()``, and +``getEndColumn()`` to obtain information about its file, start line and column, and end line and +column. + +The most important subclasses of `AstNode +`__ are `Stmt +`__ and `Expr +`__, which represent +statements and expressions, respectively. This section briefly discusses some of their more +important subclasses and predicates. For a full reference of all the subclasses of `Stmt +`__ and `Expr +`__ and their API, see +`Stmt.qll `__ and `Expr.qll +`__. + +Statements +~~~~~~~~~~ + +- ``ExprStmt``: an expression statement; use ``getExpr()`` to access the expression itself +- ``Assignment``: an assignment statement; use ``getLhs(i)`` to access the ``i``\ th left-hand side + and ``getRhs(i)`` to access the ``i``\ th right-hand side; if there is only a single left-hand side + you can use ``getLhs()`` instead, and similar for the right-hand side + + - ``SimpleAssignStmt``: an assignment statement that does not involve a compound operator + + - ``AssignStmt``: a plain assignment statement of the form ``lhs = rhs`` + - ``DefineStmt``: a short-hand variable declaration of the form ``lhs := rhs`` + + - ``CompoundAssignStmt``: an assignment statement with a compound operator, such as ``lhs += rhs`` + +- ``IncStmt``, ``DecStmt``: an increment statement or a decrement statement, respectively; use + ``getOperand()`` to access the expression being incremented or decremented +- ``BlockStmt``: a block of statements between curly braces; use ``getStmt(i)`` to access the + ``i``\ th statement in a block +- ``IfStmt``: an ``if`` statement; use ``getInit()``, ``getCond()``, ``getThen()``, and + ``getElse()`` to access the (optional) init statement, the condition being checked, the "then" + branch to evaluate if the condition is true, and the (optional) "else" branch to evaluate + otherwise, respectively +- ``LoopStmt``: a loop; use ``getBody()`` to access its body + + - ``ForStmt``: a ``for`` statement; use ``getInit()``, ``getCond()``, and ``getPost()`` to access + the init statement, loop condition, and post statement, respectively, all of which are optional + + - ``RangeStmt``: a ``range`` statement; use ``getDomain()`` to access the iteration domain, and + ``getKey()`` and ``getValue()`` to access the expressions to which successive keys and values + are assigned, if any + +- ``GoStmt``: a ``go`` statement; use ``getCall()`` to access the call expression that is evaluated + in the new goroutine +- ``DeferStmt``: a ``defer`` statement; use ``getCall()`` to access the call expression being + deferred +- ``SendStmt``: a send statement; use ``getChannel()`` and ``getValue()`` to access the channel and + the value being sent over the channel, respectively +- ``ReturnStmt``: a ``return`` statement; use ``getExpr(i)`` to access the ``i``\ th returned + expression; if there is only a single returned expression you can use ``getExpr()`` instead +- ``BranchStmt``: a statement that interrupts structured control flow; use ``getLabel()`` to get the + optional target label + + - ``BreakStmt``: a ``break`` statement + - ``ContinueStmt``: a ``continue`` statement + - ``FallthroughStmt``: a ``fallthrough`` statement at the end of a switch case + - ``GotoStmt``: a ``goto`` statement + +- ``DeclStmt``: a declaration statement, use ``getDecl()`` to access the declaration in this + statement; note that one rarely needs to deal with declaration statements directly, since + reasoning about the entities they declare is usually easier +- ``SwitchStmt``: a ``switch`` statement; use ``getInit()`` to access the (optional) init statement, + and ``getCase(i)`` to access the ``i``\ th ``case`` or ``default`` clause + + - ``ExpressionSwitchStmt``: a ``switch`` statement examining the value of an expression + - ``TypeSwitchStmt``: a ``switch`` statement examining the type of an expression + +- ``CaseClause``: a ``case`` or ``default`` clause in a ``switch`` statement; use ``getExpr(i)`` to + access the ``i``\ th expression, and ``getStmt(i)`` to access the ``i``\ th statement in the body + of this clause +- ``SelectStmt``: a ``select`` statement; use ``getCommClause(i)`` to access the ``i``\ th ``case`` + or ``default`` clause +- ``CommClause``: a ``case`` or ``default`` clause in a ``select`` statement; use ``getComm()`` to + access the send/receive statement of this clause (not defined for ``default`` clauses), and + ``getStmt(i)`` to access the ``i``\ th statement in the body of this clause +- ``RecvStmt``: a receive statement in a ``case`` clause of a ``select`` statement; use + ``getLhs(i)`` to access the ``i``\ th left-hand side of this statement, and ``getExpr()`` to + access the underlying receive expression + +Expressions +~~~~~~~~~~~ + +Class ``Expression`` has a predicate ``isConst()`` that holds if the expression is a compile-time +constant. For such constant expressions, ``getNumericValue()`` and ``getStringValue()`` can be used +to determine their numeric value and string value, respectively. Note that these predicates are not +defined for expressions whose value cannot be determined at compile time. Also note that the result +type of ``getNumericValue()`` is the QL type ``float``. If an expression has a numeric value that +cannot be represented as a QL ``float``, this predicate is also not defined. In such cases, you can +use ``getExactValue()`` to obtain a string representation of the value of the constant. + +- ``Ident``: an identifier; use ``getName()`` to access its name +- ``SelectorExpr``: a selector of the form ``base.sel``; use ``getBase()`` to access the part before + the dot, and ``getSelector()`` for the identifier after the dot +- ``BasicLit``: a literal of a basic type; subclasses ``IntLit``, ``FloatLit``, ``ImagLit``, + ``RuneLit``, and ``StringLit`` represent various specific kinds of literals +- ``FuncLit``: a function literal; use ``getBody()`` to access the body of the function +- ``CompositeLit``: a composite literal; use ``getKey(i)`` and ``getValue(i)`` to access the + ``i``\ th key and the ``i``\ th value, respectively +- ``ParenExpr``: a parenthesized expression; use ``getExpr()`` to access the expression between the + parentheses +- ``IndexExpr``: an index expression ``base[idx]``; use ``getBase()`` and ``getIndex()`` to access + ``base`` and ``idx``, respectively +- ``SliceExpr``: a slice expression ``base[lo:hi:max]``; use ``getBase()``, ``getLow()``, + ``getHigh()``, and ``getMax()`` to access ``base``, ``lo``, ``hi``, and ``max``, respectively; + note that ``lo``, ``hi``, and ``max`` can be omitted, in which case the corresponding predicates are not defined +- ``ConversionExpr``: a conversion expression ``T(e)``; use ``getTypeExpr()`` and ``getOperand()`` + to access ``T`` and ``e``, respectively +- ``TypeAssertExpr``: a type assertion ``e.(T)``; use ``getExpr()`` and ``getTypeExpr()`` to access + ``e`` and ``T``, respectively +- ``CallExpr``: a call expression ``callee(arg0, ..., argn)``; use ``getCalleeExpr()`` to access + ``callee``, and ``getArg(i)`` to access the ``i``\ th argument +- ``StarExpr``: a star expression, which may be either a pointer-type expression or a + pointer-dereference expression, depending on context; use ``getBase()`` to access the operand of + the star +- ``TypeExpr``: an expression that denotes a type +- ``OperatorExpr``: an expression with a unary or binary operator; use ``getOperator()`` to access + the operator + + - ``UnaryExpr``: an expression with a unary operator; use ``getAnOperand()`` to access the operand + of the operator + - ``BinaryExpr``: an expression with a binary operator; use ``getLeftOperand()`` and + ``getRightOperand()`` to access the left and the right operand, respectively + + - ``ComparisonExpr``: a binary expression that performs a comparison, including both equality + tests and relational comparisons + + - ``EqualityTestExpr``: an equality test, that is, either ``==`` or ``!=``; the predicate + ``getPolarity()`` has result ``true`` for the former and ``false`` for the latter + - ``RelationalComparisonExpr``: a relational comparison; use ``getLesserOperand()`` and + ``getGreaterOperand()`` to access the lesser and greater operand of the comparison, + respectively; ``isStrict()`` holds if this is a strict comparison using ``<`` or ``>``, + as opposed to ``<=`` or ``>=`` + +Names +~~~~~ + +While ``Ident`` and ``SelectorExpr`` are very useful classes, they are often too general: ``Ident`` +covers all identifiers in a program, including both identifiers appearing in a declaration as well +as references, and does not distinguish between names referring to packages, types, variables, +constants, functions, or statement labels. Similarly, a ``SelectorExpr`` might refer to a package, a +type, a function, or a method. + +Class ``Name`` and its subclasses provide a more fine-grained mapping of this space, organized along +the two axes of structure and namespace. In terms of structure, a name can be a ``SimpleName``, +meaning that it is a simple identifier (and hence an ``Ident``), or it can be a ``QualifiedName``, +meaning that it is a qualified identifier (and hence a ``SelectorExpr``). In terms of namespacing, a +``Name`` can be a ``PackageName``, ``TypeName``, ``ValueName``, or ``LabelName``. A ``ValueName``, +in turn, can be either a ``ConstantName``, a ``VariableName``, or a ``FunctionName``, depending on +what sort of entity the name refers to. + +A related abstraction is provided by class ``ReferenceExpr``: a reference expression is an +expression that refers to a variable, a constant, a function, a field, or an element of an array or +a slice. Use predicates ``isLvalue()`` and ``isRvalue()`` to determine whether a reference +expression appears in a syntactic context where it is assigned to or read from, respectively. + +Finally, ``ValueExpr`` generalizes ``ReferenceExpr`` to include all other kinds of expressions that +can be evaluated to a value (as opposed to expressions that refer to a package, a type, or a +statement label). + +Functions +~~~~~~~~~ + +At the syntactic level, functions appear in two forms: in function declarations (represented by +class ``FuncDecl``) and as function literals (represented by class ``FuncLit``). Since it is often +convenient to reason about functions of either kind, these two classes share a common superclass +``FuncDef``, which defines a few useful member predicates: + + - ``getBody()`` provides access to the function body + - ``getName()`` gets the function name; it is undefined for function literals, which do not have a + name + - ``getParameter(i)`` gets the ``i``\ th parameter of the function + - ``getResultVar(i)`` gets the ``i``\ th result variable of the function; if there is only + one result, ``getResultVar()`` can be used to access it + - ``getACall()`` gets a data-flow node (see below) representing a call to this function + +Entities and name binding +------------------------- + +Not all elements of a code base can be represented as AST nodes. For example, functions defined in +the standard library or in a dependency do not have a source-level definition within the source code +of the program itself, and built-in functions like ``len`` do not have a definition at all. Hence +functions cannot simplify be identified with their definition, and similarly for variables, types, +and so on. + +To smooth over this difference and provide a unified view of functions no matter where they are +defined, the Go library introduces the concept of an `entity`. An entity is a named program element, +that is, a package, a type, a constant, a variable, a field, a function, or a label. All entities +belong to class ``Entity``, which defines a few useful predicates: + + - ``getName()`` gets the name of the entity + - ``hasQualifiedName(pkg, n)`` holds if this entity is declared in package ``pkg`` and has name + ``n``; this predicate is only defined for types, functions, and package-level variables and + constants (but not for methods or local variables) + - ``getDeclaration()`` connects an entity to its declaring identifier, if any + - ``getAReference()`` gets a ``Name`` that refers to this entity + +Conversely, class ``Name`` defines a predicate ``getTarget()`` that gets the entity to which the +name refers. + +Class ``Entity`` has several subclasses representing specific kinds of entities: ``PackageEntity`` +for packages; ``TypeEntity`` for types; ``ValueEntity`` for constants (``Constant``), variables +(``Variable``), and functions (``Function``); and ``Label`` for statement labels. + +Class ``Variable``, in turn, has a few subclasses representing specific kinds of variables: a +``LocalVariable`` is a variable declared in a local scope, that is, not at package level; +``ReceiverVariable``, ``Parameter`` and ``ResultVariable`` describe receivers, parameters and +results, respectively, and define a predicate ``getFunction()`` to access the corresponding +function. Finally, class ``Field`` represents struct fields, and provides a member predicate +``hasQualifiedName(pkg, tp, f)`` that holds if this field has name ``f`` and belongs to type ``tp`` +in package ``pkg``. (Note that due to embedding the same field can belong to multiple types.) + +Class ``Function`` has a subclass ``Method`` representing methods (including both interface methods +and methods defined on a named type). Similar to ``Field``, ``Method`` provides a member predicate +``hasQualifiedName(pkg, tp, m)`` that holds if this method has name ``m`` and belongs to type ``tp`` +in package ``pkg``. Predicate ``implements(m2)`` holds if this method implements method ``m2``, that +is, it has the same name and signature as ``m2`` and it belongs to a type that implements the +interface to which ``m2`` belongs. For any function, ``getACall()`` provides access to call sites +that may call this function, possibly through virtual dispatch. + +Finally, module ``Builtin`` provides a convenient way of looking up the entities corresponding to +built-in functions and types. For example, ``Builtin::len()`` is the entity representing the +built-in function ``len``, ``Builtin::bool()`` is the ``bool`` type, and ``Builtin::nil()`` is the +value ``nil``. + +Type information +---------------- + +Types are represented by class ``Type`` and its subclasses, such as ``BoolType`` for the built-in +type ``bool``; ``NumericType`` for the various numeric types including ``IntType``, ``Uint8Type``, +``Float64Type`` and others; ``StringType`` for the type ``string``; ``NamedType``, ``ArrayType``, +``SliceType``, ``StructType``, ``InterfaceType``, ``PointerType``, ``MapType``, ``ChanType`` for +named types, arrays, slices, structs, interfaces, pointers, maps, and channels, respectively. +Finally, ``SignatureType`` represents function types. + +Note that the type ``BoolType`` is distinct from the entity ``Builtin::bool()``: the latter views +``bool`` as a declared entity, the former as a type. You can, however, map from types to their +corresponding entity (if any) using the predicate ``getEntity()``. + +Class ``Expr`` and class ``Entity`` both define a predicate ``getType()`` to determine the type of +an expression or entity. If the type of an expression or entity cannot be determined (for example +because some dependency could not be found during extraction), it will be associated with an invalid +type of class ``InvalidType``. + +Control flow +------------ + +Most CodeQL query writers will rarely use the control-flow representation of a program directly, but +it is nevertheless useful to understand how it works. + +Unlike the abstract syntax tree, which views the program as a hierarchy of AST nodes, the +control-flow graph views it as a collection of `control-flow nodes`, each representing a single +operation performed at runtime. These nodes are connected to each other by (directed) edges +representing the order in which operations are performed. + +For example, consider the following code snippet: + +.. code-block:: go + + x := 0 + if p != nil { + x = p.f + } + return x + +In the AST, this is represented as an ``IfStmt`` and a ``ReturnStmt``, with the former having an +``NeqExpr`` and a ``BlockStmt`` as its children, and so on. This provides a very detailed picture of +the syntactic structure of the code, but it does not immediately help us reason about the order +in which the various operations such as the comparison and the assignment are performed. + +In the CFG, there are nodes corresponding to ``x := 0``, ``p != nil``, ``x = p.f``, and ``return +x``, as well as a few others. The edges between these nodes model the possible execution orders of +these statements and expressions, and look as follows (simplified somewhat for presentational +purposes): + +|cfg| + +For example, the edge from ``p != nil`` to ``x = p.f`` models the case where the comparison +evaluates to ``true`` and the "then" branch is evaluated, while the edge from ``p != nil`` to +``return x`` models the case where the comparison evaluates to ``false`` and the "then" branch is +skipped. + +Note, in particular, that a CFG node can have multiple outgoing edges (like from ``p != nil``) as +well as multiple incoming edges (like into ``return x``) to represent control-flow branching at +runtime. + +Also note that only AST nodes that perform some kind of operation on values have a corresponding CFG +node. This includes expressions (such as the comparison ``p != nil``), assignment statements (such +as ``x = p.f``) and return statements (such as ``return x``), but not statements that serve a purely +syntactic purpose (such as block statements) and statements whose semantics is already reflected by +the CFG edges (such as ``if`` statements). + +It is important to point out that the control-flow graph provided by the CodeQL libraries for Go +only models `local` control flow, that is, flow within a single function. Flow from function calls +to the function they invoke, for example, is not represented by control-flow edges. + +In CodeQL, control-flow nodes are represented by class ``ControlFlow::Node``, and the edges between +nodes are captured by the member predicates ``getASuccessor()`` and ``getAPredecessor()`` of +``ControlFlow::Node``. In addition to control-flow nodes representing runtime operations, each +function also has a synthetic entry node and an exit node, representing the start and end of an +execution of the function, respectively. These exist to ensure that the control-flow graph +corresponding to a function has a unique entry node and a unique exit node, which is required for +many standard control-flow analysis algorithms. + +Data flow +--------- + +At the data-flow level, the program is thought of as a collection of `data-flow nodes`. These nodes +are connected to each other by (directed) edges representing the way data flows through the program +at runtime. + +For example, there are data-flow nodes corresponding to expressions and other data-flow nodes +corresponding to variables (`SSA variables +`__, to be precise). Here is the +data-flow graph corresponding to the code snippet shown above, ignoring SSA conversion for +simplicity: + +|dfg| + +Note that unlike in the control-flow graph, the assignments ``x := 0`` and ``x = p.f`` are not +represented as nodes. Instead, they are expressed as edges between the node representing the +right-hand side of the assignment and the node representing the variable on the left-hand side. For +any subsequent uses of that variable, there is a data-flow edge from the variable to that use, so by +following the edges in the data-flow graph we can trace the flow of values through variables at +runtime. + +It is important to point out that the data-flow graph provided by the CodeQL libraries for Go only +models `local` flow, that is, flow within a single function. Flow from arguments in a function call +to the corresponding function parameters, for example, is not represented by data-flow edges. + +In CodeQL, data-flow nodes are represented by class ``DataFlow::Node``, and the edges between nodes +are captured by the predicate ``DataFlow::localFlowStep``. The predicate ``DataFlow::localFlow`` +generalizes this from a single flow step to zero or more flow steps. + +Most expressions have a corresponding data-flow node; exceptions include type expressions, statement +labels and other expressions that do not have a value, as well as short-circuiting operators. To map +from the AST node of an expression to the corresponding DFG node, use ``DataFlow::exprNode``. Note +that the AST node and the DFG node are different entities and cannot be used interchangeably. + +There is also a predicate ``asExpr()`` on ``DataFlow::Node`` that allows you to recover the +expression underlying a DFG node. However, this predicate should be used with caution, since many +data-flow nodes do not correspond to an expression, and so this predicate will not be defined for +them. + +Similar to ``Expr``, ``DataFlow::Node`` has a member predicate ``getType()`` to determine the type +of a node, as well as predicates ``getNumericValue()``, ``getStringValue()``, and +``getExactValue()`` to retrieve the value of a node if it is constant. + +Important subclasses of ``DataFlow::Node`` include: + + - ``DataFlow::CallNode``: a function call or method call; use ``getArgument(i)`` and + ``getResult(i)`` to obtain the data-flow nodes corresponding to the ``i``\ th argument and the + ``i``\ th result of this call, respectively; if there is only a single result, ``getResult()`` + will return it + - ``DataFlow::ParameterNode``: a parameter of a function; use ``asParameter()`` to access the + corresponding AST node + - ``DataFlow::BinaryOperationNode``: an operation involving a binary operator; each ``BinaryExpr`` + has a corresponding ``BinaryOperationNode``, but there are also binary operations that are not + explicit at the AST level, such as those arising from compound assignments and + increment/decrement statements; at the AST level, ``x + 1``, ``x += 1``, and ``x++`` are + represented by different kinds of AST nodes, while at the DFG level they are all modeled as a + binary operation node with operands ``x`` and ``1`` + - ``DataFlow::UnaryOperationNode``: analogous, but for unary operators + + - ``DataFlow::PointerDereferenceNode``: a pointer dereference, either explicit in an expression + of the form ``*p``, or implicit in a field or method reference through a pointer + - ``DataFlow::AddressOperationNode``: analogous, but for taking the address of an entity + - ``DataFlow::RelationalComparisonNode``, ``DataFlow::EqualityTestNode``: data-flow nodes + corresponding to ``RelationalComparisonExpr`` and ``EqualityTestExpr`` AST nodes + +Finally, classes ``Read`` and ``Write`` represent, respectively, a read or a write of a variable, a +field, or an element of an array, a slice or a map. Use their member predicates ``readsVariable``, +``writesVariable``, ``readsField``, ``writesField``, ``readsElement``, and ``writesElement`` to +determine what the read/write refers to. + +Call graph +---------- + +The call graph connects function (and method) calls to the functions they invoke. Call graph +information is made available by two member predicates on ``DataFlow::CallNode``: ``getTarget()`` +returns the declared target of a call, while ``getACallee()`` returns all possible actual functions +a call may invoke at runtime. + +These two predicates differ in how they handle calls to interface methods: while ``getTarget()`` +will return the interface method itself, ``getACallee()`` will return all concrete methods that +implement the interface method. + +Global data flow and taint tracking +----------------------------------- + +The predicates ``DataFlow::localFlowStep`` and ``DataFlow::localFlow`` are useful for reasoning +about the flow of values in a single function. However, more advanced use cases, particularly in +security analysis, will invariably require reasoning about global data flow, including flow into, +out of, and across function calls, and through fields. + +In CodeQL, such reasoning is expressed in terms of `data-flow configurations`. A data-flow +configuration has three ingredients: sources, sinks, and barriers (also called sanitizers), all of +which are sets of data-flow nodes. Given these three sets, CodeQL provides a general mechanism for +finding paths from a source to a sink, possibly going into and out of functions and fields, but +never flowing through a barrier. + +To define a data-flow configuration, you can define a subclass of ``DataFlow::Configuration``, +overriding the member predicates ``isSource``, ``isSink``, and ``isBarrier`` to define the sets of +sources, sinks, and barriers. + +Going beyond pure data flow, many security analyses need to perform more general `taint tracking`, +which also considers flow through value-transforming operations such as string operations. To track +taint, you can define a subclass of ``TaintTracking::Configuration``, which works similar to +data-flow configurations. + +A detailed exposition of global data flow and taint tracking is out of scope for this brief +introduction. For a general overview of data flow and taint tracking, see `About data flow analysis `__. + +Advanced libraries +------------------ + +Finally, we briefly describe a few concepts and libraries that are useful for advanced query +writers. + +Basic blocks and dominance +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many important control-flow analyses organize control-flow nodes into `basic blocks +`__, which are maximal straight-line sequences of +control-flow nodes without any branching. In the CodeQL libraries, basic blocks are represented by +class ``BasicBlock``. Each control-flow node belongs to a basic block. You can use the predicate +``getBasicBlock()`` in class ``ControlFlow::Node`` and the predicate ``getNode(i)`` in +``BasicBlock`` to move from one to the other. + +Dominance is a standard concept in control-flow analysis: a basic block ``dom`` is said to +`dominate` a basic block ``bb`` if any path through the control-flow graph from the entry node to +the first node of ``bb`` must pass through ``dom``. In other words, whenever program execution +reaches the beginning of ``bb``, it must have come through ``dom``. Each basic block is moreover +considered to dominate itself. + +Dually, a basic block ``postdom`` is said to `post-dominate` a basic block ``bb`` if any path +through the control-flow graph from the last node of ``bb`` to the exit node must pass through +``postdom``. In other words, after program execution leaves ``bb``, it must eventually reach +``postdom``. + +These two concepts are captured by two member predicates ``dominates`` and ``postDominates`` of class +``BasicBlock``. + +Condition guard nodes +~~~~~~~~~~~~~~~~~~~~~ + +A condition guard node is a synthetic control-flow node that records the fact that at some point in +the control-flow graph the truth value of a condition is known. For example, consider again the code snippet we saw above: + +.. code-block:: go + + x := 0 + if p != nil { + x = p.f + } + return x + +At the beginning of the "then" branch ``p`` is known not be ``nil``. This knowledge is encoded in +the control-flow graph by a condition guard node preceding the assignment to ``x``, recording the +fact that ``p != nil`` is ``true`` at this point: + +|cfg2| + +A typical use of this information would be in an analyis that looks for ``nil`` dereferences: such +an analysis would be able to conclude that the field read ``p.f`` is safe because it is immediately +preceded by a condition guard node guaranteeing that ``p`` is not ``nil``. + +In CodeQL, condition guard nodes are represented by class ``ControlFlow::ConditionGuardNode`` which +offers a variety of member predicates to reason about which conditions a guard node guarantees. + +Static single-assignment form +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +`Static single-assignment form `__ (SSA +form for short) is a program representation in which the original program variables are mapped onto +more fine-grained `SSA variables`. Each SSA variable has exactly one definition, so program +variables with multiple assignments correspond to multiple SSA variables. + +Most of the time query authors do not have to deal with SSA form directly. The data-flow graph uses +it under the hood, and so most of the benefits derived from SSA can be gained by simply using the +data-flow graph. + +For example, the data-flow graph for our running example actually looks more like this: + +|ssa| + +Note that the program variable ``x`` has been mapped onto three distinct SSA variables ``x1``, +``x2``, and ``x3``. In this case there is not much benefit to such a representation, but in general +SSA form has well-known advantages for data-flow analysis for which we refer to the literature. + +If you do need to work with raw SSA variables, they are represented by the class ``SsaVariable``. +Class ``SsaDefinition`` represents definitions of SSA variables, which have a one-to-one +correspondence with ``SsaVariable``\ s. Member predicates ``getDefinition()`` and ``getVariable()`` +exist to map from one to the other. You can use member predicate ``getAUse()`` of ``SsaVariable`` to +look for uses of an SSA variable. To access the program variable underlying an SSA variable, use +member predicate ``getSourceVariable()``. + +Global value numbering +~~~~~~~~~~~~~~~~~~~~~~ + +`Global value numbering `__ is a technique for +determining when two computations in a program are guaranteed to yield the same result. This is done +by associating with each data-flow node an abstract representation of its value (conventionally +called a `value number`, even though in practice it is not usually a number) such that identical +computations are represented by identical value numbers. + +Since this is an undecidable problem, global value numbering is `conservative` in the sense that if +two data-flow nodes have the same value number they are guaranteed to have the same value at +runtime, but not conversely. (That is, there may be data-flow nodes that do, in fact, always +evaluate to the same value, but their value numbers are different.) + +In the CodeQL libraries for Go, you can use the ``globalValueNumber(nd)`` predicate to compute the +global value number for a data-flow node ``nd``. Value numbers are represented as an opaque QL type +``GVN`` that provides very little information. Usually, all you need to do with global value numbers +is to compare them to each other to determine whether two data-flow nodes have the same value. + +Further reading +--------------- + +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. + +.. |ast| image:: ast.png +.. |cfg| image:: cfg.png +.. |dfg| image:: dfg.png +.. |cfg2| image:: cfg2.png +.. |ssa| image:: ssa.png diff --git a/docs/language/learn-ql/go/ql-for-go.rst b/docs/language/learn-ql/go/ql-for-go.rst index baa390dc7c6..a0e04cf0370 100644 --- a/docs/language/learn-ql/go/ql-for-go.rst +++ b/docs/language/learn-ql/go/ql-for-go.rst @@ -1,12 +1,18 @@ CodeQL for Go ============= -This page provides an overview of the CodeQL for Go documentation that is currently available. +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Go codebases. -- `Basic Go query `__ describes how to write and run queries using LGTM. +.. toctree:: + :hidden: + introduce-libraries-go -Other resources +- `Basic Go query `__: Learn to write and run a simple CodeQL query using LGTM. + +- :doc:`CodeQL library for Go `: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go. + +Further reading --------------- - For the queries used in LGTM, display a `Go query `__ and click **Open in query console** to see the code used to find alerts. diff --git a/docs/language/learn-ql/go/ssa.dot b/docs/language/learn-ql/go/ssa.dot new file mode 100644 index 00000000000..c8bfb8c62a0 --- /dev/null +++ b/docs/language/learn-ql/go/ssa.dot @@ -0,0 +1,15 @@ +digraph ssa { + graph [dpi=300]; + rankdir=LR; + + "x1" [shape=diamond,label=1>]; + "x2" [shape=diamond,label=2>]; + "x3" [shape=diamond,label=3>]; + "return x" [label=x>]; + + "0" -> "x1"; + "p.f" -> "x2"; + "x1" -> "x3"; + "x2" -> "x3"; + "x3" -> "return x"; +} diff --git a/docs/language/learn-ql/go/ssa.png b/docs/language/learn-ql/go/ssa.png new file mode 100644 index 00000000000..cd5ba3f29de Binary files /dev/null and b/docs/language/learn-ql/go/ssa.png differ diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 5adafde09e9..e5617299436 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -4,7 +4,7 @@ Learning CodeQL CodeQL is the code analysis platform used by security researchers to automate variant analysis. You can use CodeQL queries to explore code and quickly find variants of security vulnerabilities and bugs. These queries are easy to write and share–visit the topics below and `our open source repository on GitHub `__ to learn more. -You can also try out CodeQL in the `query console `__ on `LGTM.com `__. +You can also try out CodeQL in the `query console on LGTM.com `__. Here, you can query open source projects directly, without having to download CodeQL databases and libraries. CodeQL is based on a powerful query language called QL. The following topics help you understand QL in general, as well as how to use it when analyzing code with CodeQL. @@ -15,85 +15,26 @@ CodeQL is based on a powerful query language called QL. The following topics hel If you've previously used QL, you may notice slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. -.. toctree:: - :hidden: - - terminology-note - - -.. _getting-started: - -Getting started -*************** - -If you are new to QL, start by looking at the following topics: - .. toctree:: :maxdepth: 1 - introduction-to-ql - about-ql beginner/ql-tutorials - ql-etudes/river-crossing - -CodeQL training and variant analysis examples -********************************************* - -To start learning how to use CodeQL for variant analysis for code written in a specific language, see: - -.. toctree:: - :maxdepth: -1 - - ql-training - -.. _writing-ql-queries: - -Writing CodeQL queries -********************** - -To learn more about writing your own queries, see: - -.. toctree:: - :maxdepth: 3 - :includehidden: - writing-queries/writing-queries - -For more information on using CodeQL to query code written in a specific language, see: - -.. toctree:: - :maxdepth: 2 - :includehidden: - cpp/ql-for-cpp csharp/ql-for-csharp go/ql-for-go java/ql-for-java javascript/ql-for-javascript python/ql-for-python - -Technical information -********************* - -For more technical information see: + ql-training + technical-info .. toctree:: - :maxdepth: 2 - :includehidden: + :hidden: + + terminology-note - technical-info +Further reading +*************** -Reference topics -**************** - -For a more comprehensive guide to the query language itself, see the following reference topics: - -- `QL language handbook `__—a description of important concepts in QL. -- `QL language specification `__—a formal specification of QL. - -Search -****** - -.. * :ref:`genindex` remove index for the time being as we currently have no tags - -* :ref:`search` +- `QL language reference `__: A description of important concepts in QL and a formal specification of the QL language. diff --git a/docs/language/learn-ql/intro-to-data-flow.rst b/docs/language/learn-ql/intro-to-data-flow.rst index f266849dfa7..e509d3a8c16 100644 --- a/docs/language/learn-ql/intro-to-data-flow.rst +++ b/docs/language/learn-ql/intro-to-data-flow.rst @@ -1,10 +1,11 @@ -Introduction to data flow analysis with CodeQL -############################################## +About data flow analysis +######################## + +Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. Overview ******** -Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. Many CodeQL security queries implement data flow analysis, which can highlight the fate of potentially malicious or insecure data that can cause vulnerabilities in your code base. These queries help you understand if data is used in an insecure way, whether dangerous arguments are passed to functions, or whether sensitive data can leak. As well as highlighting potential security issues, you can also use data flow analysis to understand other aspects of how a program behaves, by finding, for example, uses of uninitialized variables and resource leaks. @@ -17,13 +18,13 @@ See the following tutorials for more information about analyzing data flow in sp - :doc:`Analyzing data flow in C# ` - :doc:`Analyzing data flow in Java ` - :doc:`Analyzing data flow in JavaScript/TypeScript ` -- :doc:`Taint tracking and data flow analysis in Python ` +- :doc:`Analyzing data flow and tracking tainted data in Python ` .. pull-quote:: Note - Data flow analysis is used extensively in path queries. To learn more about path queries, see :doc:`Constructing path queries `. + Data flow analysis is used extensively in path queries. To learn more about path queries, see :doc:`Creating path queries `. .. _data-flow-graph: diff --git a/docs/language/learn-ql/introduction-to-ql.rst b/docs/language/learn-ql/introduction-to-ql.rst index 4945d713803..9deb7523661 100644 --- a/docs/language/learn-ql/introduction-to-ql.rst +++ b/docs/language/learn-ql/introduction-to-ql.rst @@ -1,22 +1,21 @@ Introduction to QL ================== -QL is the powerful query language that underlies CodeQL, which is used to analyze code. -Queries written with CodeQL can find errors and uncover variants of important security vulnerabilities. -Visit `GitHub Security Lab `__ to read about examples of vulnerabilities that we have recently found in open source projects. - -Before diving into code analysis with CodeQL, it can be helpful to learn about the underlying language more generally. - -QL is a logic programming language, so it is built up of logical formulas. QL uses common logical connectives (such as ``and``, ``or``, and ``not``), quantifiers (such as ``forall`` and ``exists``), and other important logical concepts such as predicates. - -QL also supports recursion and aggregates. This allows you to write complex recursive queries using simple QL syntax and directly use aggregates such as ``count``, ``sum``, and ``average``. +Work through some simple exercises and examples to learn about the basics of QL and CodeQL. Basic syntax ------------ The basic syntax of QL will look familiar to anyone who has used SQL, but it is used somewhat differently. -A query is defined by a **select** clause, which specifies what the result of the query should be. You can try out the examples and exercises in this topic directly in LGTM. Open the `query console `__. Before you can run a query, you need to select a language and project to query (for these logic examples, any language and project will do). +QL is a logic programming language, so it is built up of logical formulas. QL uses common logical connectives (such as ``and``, ``or``, and ``not``), quantifiers (such as ``forall`` and ``exists``), and other important logical concepts such as predicates. + +QL also supports recursion and aggregates. This allows you to write complex recursive queries using simple QL syntax and directly use aggregates such as ``count``, ``sum``, and ``average``. + +Running a query +--------------- + +You can try out the following examples and exercises using `CodeQL for VS Code `__, or you can run them in the `query console on LGTM.com `__. Before you can run a query on LGTM.com, you need to select a language and project to query (for these logic examples, any language and project will do). Once you have selected a language, the query console is populated with the query: @@ -26,7 +25,7 @@ Once you have selected a language, the query console is populated with the query select "hello world" -This query simply returns the string ``"hello world"``. +This query returns the string ``"hello world"``. More complicated queries typically look like this: @@ -49,14 +48,14 @@ Note that ``int`` specifies that the **type** of ``x`` and ``y`` is 'integer'. T Simple exercises ---------------- -You can try to write simple queries using the some of the basic functions that are available for the ``integer``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, simply append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. +You can write simple queries using the some of the basic functions that are available for the ``int``, ``date``, ``float``, ``boolean`` and ``string`` types. To apply a function, append it to the argument. For example, ``1.toString()`` converts the value ``1`` to a string. Notice that as you start typing a function, a pop-up is displayed making it easy to select the function that you want. Also note that you can apply multiple functions in succession. For example, ``100.log().sqrt()`` first takes the natural logarithm of 100 and then computes the square root of the result. Exercise 1 ~~~~~~~~~~ Write a query which returns the length of the string ``"lgtm"``. (Hint: `here `__ is the list of the functions that can be applied to strings.) -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ There is often more than one way to define a query. For example, we can also write the above query in the shorter form: @@ -69,24 +68,24 @@ Exercise 2 Write a query which returns the sine of the minimum of ``3^5`` (``3`` raised to the power ``5``) and ``245.6``. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ Exercise 3 ~~~~~~~~~~ Write a query which returns the opposite of the boolean ``false``. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ Exercise 4 ~~~~~~~~~~ Write a query which computes the number of days between June 10 and September 28, 2017. -➤ `Answer `__ +➤ `See answer in the query console on LGTM.com `__ -Example queries ---------------- +Example query with multiple results +----------------------------------- The exercises above all show queries with exactly one result, but in fact many queries have multiple results. For example, the following query computes all `Pythagorean triples `__ between 1 and 10: @@ -97,7 +96,7 @@ The exercises above all show queries with exactly one result, but in fact many q x*x + y*y = z*z select x, y, z -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ To simplify the query, we can introduce a class ``SmallInt`` representing the integers between 1 and 10. We can also define a predicate ``square()`` on integers in that class. Defining classes and predicates in this way makes it easy to reuse code without having to repeat it every time. @@ -112,17 +111,18 @@ To simplify the query, we can introduce a class ``SmallInt`` representing the in where x.square() + y.square() = z.square() select x, y, z -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ -Now that you've seen some general examples, let's use the CodeQL libraries to analyze projects. -In particular, LGTM generates a database representing the code and then CodeQL is used to query this database. See `Database generation `__ for more details on how the database is built. +Example CodeQL queries +---------------------- -.. XX: Perhaps a link to the "CodeQL libraries for X"? +The previous examples used the primitive types built in to QL. Although we chose a project to query, we didn't use the information in that project's database. +The following example queries *do* use these databases and give you an idea of how to use CodeQL to analyze projects. -The previous exercises just used the primitive types built in to QL. Although we chose a project to query, they did not use the project-specific database. The following example queries *do* use these databases and give you an idea of what CodeQL can be used for. There are more details about how to use CodeQL `below <#learning-ql>`__, so don't worry if you don't fully understand these examples yet! +Queries using the CodeQL libraries can find errors and uncover variants of important security vulnerabilities in codebases. +Visit `GitHub Security Lab `__ to read about examples of vulnerabilities that we have recently found in open source projects. -Python -~~~~~~ +To import the CodeQL library for a specific programming language, type ``import `` at the start of the query. .. code-block:: ql @@ -132,10 +132,7 @@ Python where count(f.getAnArg()) > 7 select f -➤ `See this in the query console `__. The ``from`` clause defines a variable ``f`` representing a function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. - -JavaScript -~~~~~~~~~~ +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``f`` representing a Python function. The ``where`` part limits the functions ``f`` to those with more than 7 arguments. Finally, the ``select`` clause lists these functions. .. code-block:: ql @@ -145,10 +142,7 @@ JavaScript where c.getText().regexpMatch("(?si).*\\bTODO\\b.*") select c -➤ `See this in the query console `__. The ``from`` clause defines a variable ``c`` representing a comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. - -Java -~~~~ +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``c`` representing a JavaScript comment. The ``where`` part limits the comments ``c`` to those containing the word ``"TODO"``. The ``select`` clause lists these comments. .. code-block:: ql @@ -158,11 +152,11 @@ Java where not exists(p.getAnAccess()) select p -➤ `See this in the query console `__. The ``from`` clause defines a variable ``p`` representing a parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. +➤ `See this in the query console on LGTM.com `__. The ``from`` clause defines a variable ``p`` representing a Java parameter. The ``where`` clause finds unused parameters by limiting the parameters ``p`` to those which are not accessed. Finally, the ``select`` clause lists these parameters. -Learning CodeQL +Further reading --------------- -- To find out more about how to write your own queries, try working through the :doc:`QL detective tutorials `. +- To find out more about how to write your own queries, try working through the :doc:`QL tutorials `. - For an overview of the other available resources, see :doc:`Learning CodeQL <../index>`. -- For a more technical description of the underlying language, see :doc:`About QL `. +- For a more technical description of the underlying language, see the `QL language reference `__. \ No newline at end of file diff --git a/docs/language/learn-ql/java/annotations.rst b/docs/language/learn-ql/java/annotations.rst index 9fbb70776c4..497f20e1ff3 100644 --- a/docs/language/learn-ql/java/annotations.rst +++ b/docs/language/learn-ql/java/annotations.rst @@ -1,19 +1,19 @@ -Tutorial: Annotations -===================== - -Overview --------- +Annotations in Java +=================== CodeQL databases of Java projects contain information about all annotations attached to program elements. -Annotations are represented by the following CodeQL classes: +About working with annotations +------------------------------ + +Annotations are represented by these CodeQL classes: - The class ``Annotatable`` represents all entities that may have an annotation attached to them (that is, packages, reference types, fields, methods, and local variables). - The class ``AnnotationType`` represents a Java annotation type, such as ``java.lang.Override``; annotation types are interfaces. - The class ``AnnotationElement`` represents an annotation element, that is, a member of an annotation type. - The class ``Annotation`` represents an annotation such as ``@Override``; annotation values can be accessed through member predicate ``getValue``. -As an example, recall that the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings. It is defined as follows: +For example, the Java standard library defines an annotation ``SuppressWarnings`` that instructs the compiler not to emit certain kinds of warnings: .. code-block:: java @@ -25,7 +25,7 @@ As an example, recall that the Java standard library defines an annotation ``Sup ``SuppressWarnings`` is represented as an ``AnnotationType``, with ``value`` as its only ``AnnotationElement``. -A typical usage of ``SuppressWarnings`` would be the following annotation to prevent a warning about using raw types: +A typical usage of ``SuppressWarnings`` would be this annotation for preventing a warning about using raw types: .. code-block:: java @@ -37,7 +37,7 @@ A typical usage of ``SuppressWarnings`` would be the following annotation to pre The expression ``@SuppressWarnings("rawtypes")`` is represented as an ``Annotation``. The string literal ``"rawtypes"`` is used to initialize the annotation element ``value``, and its value can be extracted from the annotation by means of the ``getValue`` predicate. -We could then write the following query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element: +We could then write this query to find all ``@SuppressWarnings`` annotations attached to constructors, and return both the annotation itself and the value of its ``value`` element: .. code-block:: ql @@ -49,7 +49,7 @@ We could then write the following query to find all ``@SuppressWarnings`` annota anntp.hasQualifiedName("java.lang", "SuppressWarnings") select ann, ann.getValue("value") -➤ `See the full query in the query console `__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above. +➤ `See the full query in the query console on LGTM.com `__. Several of the LGTM.com demo projects use the ``@SuppressWarnings`` annotation. Looking at the ``value``\ s of the annotation element returned by the query, we can see that the *apache/activemq* project uses the ``"rawtypes"`` value described above. As another example, this query finds all annotation types that only have a single annotation element, which has name ``value``: @@ -64,14 +64,14 @@ As another example, this query finds all annotation types that only have a singl ) select anntp -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. Example: Finding missing ``@Override`` annotations -------------------------------------------------- -In newer versions of Java, it is recommended (though not required) to annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended. +In newer versions of Java, it's recommended (though not required) that you annotate methods that override another method with an ``@Override`` annotation. These annotations, which are checked by the compiler, serve as documentation, and also help you avoid accidental overloading where overriding was intended. -For example, consider the following example program: +For example, consider this example program: .. code-block:: java @@ -89,9 +89,9 @@ For example, consider the following example program: Here, both ``Sub1.m`` and ``Sub2.m`` override ``Super.m``, but only ``Sub1.m`` is annotated with ``@Override``. -We will now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not. +We'll now develop a query for finding methods like ``Sub2.m`` that should be annotated with ``@Override``, but are not. -As a first step, let us write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query as follows: +As a first step, let's write a query that finds all ``@Override`` annotations. Annotations are expressions, so their type can be accessed using ``getType``. Annotation types, on the other hand, are interfaces, so their qualified name can be queried using ``hasQualifiedName``. Therefore we can implement the query like this: .. code-block:: ql @@ -111,7 +111,7 @@ As always, it is a good idea to try this query on a CodeQL database for a Java p } } -This makes it very easy to write our query for finding methods that override another method, but do not have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation. +This makes it very easy to write our query for finding methods that override another method, but don't have an ``@Override`` annotation: we use predicate ``overrides`` to find out whether one method overrides another, and predicate ``getAnAnnotation`` (available on any ``Annotatable``) to retrieve some annotation. .. code-block:: ql @@ -122,14 +122,14 @@ This makes it very easy to write our query for finding methods that override ano not overriding.getAnAnnotation() instanceof OverrideAnnotation select overriding, "Method overrides another method, but does not have an @Override annotation." -➤ `See this in the query console `__. In practice, this query may yield many results from compiled library code, which are not very interesting. Therefore, it is a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. +➤ `See this in the query console on LGTM.com `__. In practice, this query may yield many results from compiled library code, which aren't very interesting. It's therefore a good idea to add another conjunct ``overriding.fromSource()`` to restrict the result to only report methods for which source code is available. Example: Finding calls to deprecated methods -------------------------------------------- As another example, we can write a query that finds calls to methods marked with a ``@Deprecated`` annotation. -For example, consider the following example program: +For example, consider this example program: .. code-block:: java @@ -147,7 +147,7 @@ For example, consider the following example program: Here, both ``A.m`` and ``A.n`` are marked as deprecated. Methods ``n`` and ``r`` both call ``m``, but note that ``n`` itself is deprecated, so we probably should not warn about this call. -Like in the previous example, we start by defining a class for representing ``@Deprecated`` annotations: +As in the previous example, we'll start by defining a class for representing ``@Deprecated`` annotations: .. code-block:: ql @@ -167,7 +167,7 @@ Now we can define a class for representing deprecated methods: } } -Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods (see :doc:`Tutorial: Navigating the call graph ` for more information on class ``Call``): +Finally, we use these classes to find calls to deprecated methods, excluding calls that themselves appear in deprecated methods: .. code-block:: ql @@ -178,7 +178,9 @@ Finally, we use these classes to find calls to deprecated methods, excluding cal and not call.getCaller() instanceof DeprecatedMethod select call, "This call invokes a deprecated method." -On our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``. +In our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``. + +For more information about the class ``Call``, see :doc:`Navigating the call graph `. Improvements ~~~~~~~~~~~~ @@ -233,11 +235,11 @@ Now we can extend our query to filter out calls in methods carrying a ``Suppress and not call.getCaller().getAnAnnotation() instanceof SuppressDeprecationWarningAnnotation select call, "This call invokes a deprecated method." -➤ `See this in the query console `__. It's fairly common for projects to contain calls to methods that appear to be deprecated. +➤ `See this in the query console on LGTM.com `__. It's fairly common for projects to contain calls to methods that appear to be deprecated. -What next? ----------- +Further reading +--------------- -- Take a look at some of the other tutorials: :doc:`Tutorial: Javadoc ` and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Take a look at some of the other articles in this section: :doc:`Javadoc ` and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/ast-class-reference.rst b/docs/language/learn-ql/java/ast-class-reference.rst index 268b95acac5..f34e2eec764 100644 --- a/docs/language/learn-ql/java/ast-class-reference.rst +++ b/docs/language/learn-ql/java/ast-class-reference.rst @@ -1,5 +1,7 @@ -AST class reference -=================== +Classes for working with Java code +================================== + +CodeQL has a large selection of classes for working with Java statements and expressions. .. _Expr: https://help.semmle.com/qldoc/java/semmle/code/java/Expr.qll/type.Expr$Expr.html .. _Stmt: https://help.semmle.com/qldoc/java/semmle/code/java/Statement.qll/type.Statement$Stmt.html diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index cfaa33cad9f..6f7874c772f 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -1,8 +1,10 @@ -Tutorial: Navigating the call graph -=================================== +Navigating the call graph +========================= -Call graph API --------------- +CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. + +Call graph classes +------------------ The CodeQL library for Java provides two abstract classes for representing a program's call graph: ``Callable`` and ``Call``. The former is simply the common superclass of ``Method`` and ``Constructor``, the latter is a common superclass of ``MethodAccess``, ``ClassInstanceExpression``, ``ThisConstructorInvocationStmt`` and ``SuperConstructorInvocationStmt``. Simply put, a ``Callable`` is something that can be invoked, and a ``Call`` is something that invokes a ``Callable``. @@ -56,7 +58,7 @@ Class ``Call`` provides two call graph navigation predicates: For instance, in our example ``getCallee`` of the second call in ``Client.main`` would return ``Super.getX``. At runtime, though, this call would actually invoke ``Sub.getX``. -Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are as follows: +Class ``Callable`` defines a large number of member predicates; for our purposes, the two most important ones are: - ``calls(Callable target)`` succeeds if this callable contains a call whose callee is ``target``. - ``polyCalls(Callable target)`` succeeds if this callable may call ``target`` at runtime; this is the case if it contains a call whose callee is either ``target`` or a method that ``target`` overrides. @@ -66,7 +68,7 @@ In our example, ``Client.main`` calls the constructor ``Sub(int)`` and the metho Example: Finding unused methods ------------------------------- -Given this API, we can easily write a query that finds methods that are not called by any other method: +We can use the ``Callable`` class to write a query that finds methods that are not called by any other method: .. code-block:: ql @@ -76,7 +78,7 @@ Given this API, we can easily write a query that finds methods that are not call where not exists(Callable caller | caller.polyCalls(callee)) select callee -➤ `See this in the query console `__. This simple query typically returns a large number of results. +➤ `See this in the query console on LGTM.com `__. This simple query typically returns a large number of results. .. pull-quote:: @@ -84,7 +86,7 @@ Given this API, we can easily write a query that finds methods that are not call We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding. -Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query as follows: +Running this query on a typical Java project results in lots of hits in the Java standard library. This makes sense, since no single client program uses every method of the standard library. More generally, we may want to exclude methods and constructors from compiled libraries. We can use the predicate ``fromSource`` to check whether a compilation unit is a source file, and refine our query: .. code-block:: ql @@ -95,7 +97,7 @@ Running this query on a typical Java project results in lots of hits in the Java callee.getCompilationUnit().fromSource() select callee, "Not called." -➤ `See this in the query console `__. This change reduces the number of results returned for most projects. +➤ `See this in the query console on LGTM.com `__. This change reduces the number of results returned for most projects. We might also notice several unused methods with the somewhat strange name ````: these are class initializers; while they are not explicitly called anywhere in the code, they are called implicitly whenever the surrounding class is loaded. Hence it makes sense to exclude them from our query. While we are at it, we can also exclude finalizers, which are similarly invoked implicitly: @@ -109,7 +111,7 @@ We might also notice several unused methods with the somewhat strange name ``") and not callee.hasName("finalize") select callee, "Not called." -➤ `See this in the query console `__. This also reduces the number of results returned by most projects. +➤ `See this in the query console on LGTM.com `__. This also reduces the number of results returned by most projects. We may also want to exclude public methods from our query, since they may be external API entry points: @@ -124,7 +126,7 @@ We may also want to exclude public methods from our query, since they may be ext not callee.isPublic() select callee, "Not called." -➤ `See this in the query console `__. This should have a more noticeable effect on the number of results returned. +➤ `See this in the query console on LGTM.com `__. This should have a more noticeable effect on the number of results returned. A further special case is non-public default constructors: in the singleton pattern, for example, a class is provided with private empty default constructor to prevent it from being instantiated. Since the very purpose of such constructors is their not being called, they should not be flagged up: @@ -140,9 +142,9 @@ A further special case is non-public default constructors: in the singleton patt not callee.(Constructor).getNumberOfParameters() = 0 select callee, "Not called." -➤ `See this in the query console `__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects. +➤ `See this in the query console on LGTM.com `__. This change has a large effect on the results for some projects but little effect on the results for others. Use of this pattern varies widely between different projects. -Finally, on many Java projects there are methods that are invoked indirectly by reflection. Thus, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes: +Finally, on many Java projects there are methods that are invoked indirectly by reflection. So, while there are no calls invoking these methods, they are, in fact, used. It is in general very hard to identify such methods. A very common special case, however, is JUnit test methods, which are reflectively invoked by a test runner. The QL Java library has support for recognizing test classes of JUnit and other testing frameworks, which we can employ to filter out methods defined in such classes: .. code-block:: ql @@ -157,11 +159,11 @@ Finally, on many Java projects there are methods that are invoked indirectly by not callee.getDeclaringType() instanceof TestClass select callee, "Not called." -➤ `See this in the query console `__. This should give a further reduction in the number of results returned. +➤ `See this in the query console on LGTM.com `__. This should give a further reduction in the number of results returned. -What next? ----------- +Further reading +--------------- -- Find out how to query metadata and white space: :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out how to query metadata and white space: :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/dataflow.rst b/docs/language/learn-ql/java/dataflow.rst index 98b8b97e153..d49128113ba 100644 --- a/docs/language/learn-ql/java/dataflow.rst +++ b/docs/language/learn-ql/java/dataflow.rst @@ -1,13 +1,15 @@ Analyzing data flow in Java -============================ +=========================== -Overview --------- +You can use CodeQL to track the flow of data through a Java program to its use. -This topic describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. +About this article +------------------ -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +This article describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries. +The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking. + +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Local data flow --------------- @@ -17,7 +19,7 @@ Local data flow is data flow within a single method or callable. Local data flow Using local data flow ~~~~~~~~~~~~~~~~~~~~~ -The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). It is possible to map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: +The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). You can map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``: .. code-block:: ql @@ -45,9 +47,9 @@ or using the predicates ``exprNode`` and ``parameterNode``: */ ParameterNode parameterNode(Parameter p) { ... } -The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localFlow``, which is equivalent to ``localFlowStep*``. +The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively by using the ``+`` and ``*`` operators, or by using the predefined recursive predicate ``localFlow``, which is equivalent to ``localFlowStep*``. -For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -65,9 +67,9 @@ Local taint tracking extends local data flow by including non-value-preserving f If ``x`` is a tainted string then ``y`` is also tainted. -The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localTaint``, which is equivalent to ``localTaintStep*``. +The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. You can apply the predicate recursively by using the ``+`` and ``*`` operators, or by using the predefined recursive predicate ``localTaint``, which is equivalent to ``localTaintStep*``. -For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows: +For example, you can find taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps: .. code-block:: ql @@ -76,7 +78,7 @@ For example, finding taint propagation from a parameter ``source`` to an express Examples ~~~~~~~~ -The following query finds the filename passed to ``new FileReader(..)``. +This query finds the filename passed to ``new FileReader(..)``. .. code-block:: ql @@ -88,7 +90,7 @@ The following query finds the filename passed to ``new FileReader(..)``. call.getCallee() = fileReader select call.getArgument(0) -Unfortunately, this will only give the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument: +Unfortunately, this only gives the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument: .. code-block:: ql @@ -102,7 +104,7 @@ Unfortunately, this will only give the expression in the argument, not the value DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0))) select src -Then we can make the source more specific, for example an access to a public parameter. The following query finds where a public parameter is passed to ``new FileReader(..)``: +Then we can make the source more specific, for example an access to a public parameter. This query finds where a public parameter is passed to ``new FileReader(..)``: .. code-block:: ql @@ -116,7 +118,7 @@ Then we can make the source more specific, for example an access to a public par DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(call.getArgument(0))) select p -The following example finds calls to formatting functions where the format string is not hard-coded. +This query finds calls to formatting functions where the format string is not hard-coded. .. code-block:: ql @@ -148,7 +150,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor Using global data flow ~~~~~~~~~~~~~~~~~~~~~~ -The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows: +You use the global data flow library by extending the class ``DataFlow::Configuration``: .. code-block:: ql @@ -166,7 +168,7 @@ The global data flow library is used by extending the class ``DataFlow::Configur } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: - ``isSource``—defines where data may flow from - ``isSink``—defines where data may flow to @@ -186,7 +188,7 @@ The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node Using global taint tracking ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Global taint tracking is to global data flow as local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows: +Global taint tracking is to global data flow as local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. You use the global taint tracking library by extending the class ``TaintTracking::Configuration``: .. code-block:: ql @@ -204,7 +206,7 @@ Global taint tracking is to global data flow as local taint tracking is to local } } -The following predicates are defined in the configuration: +These predicates are defined in the configuration: - ``isSource``—defines where taint may flow from - ``isSink``—defines where taint may flow to @@ -223,7 +225,7 @@ The data flow library contains some predefined flow sources. The class ``RemoteF Examples ~~~~~~~~ -The following example shows a taint-tracking configuration that uses remote user input as data sources. +This query shows a taint-tracking configuration that uses remote user input as data sources. .. code-block:: ql @@ -251,12 +253,12 @@ Exercise 3: Write a class that represents flow sources from ``java.lang.System.g Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from ``getenv`` to ``java.net.URL``. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- -- Try the worked examples in the following topics: :doc:`Tutorial: Navigating the call graph ` and :doc:`Tutorial: Working with source locations `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Try the worked examples in these articles: :doc:`Navigating the call graph ` and :doc:`Working with source locations `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. Answers ------- diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index 25d605b18b8..24fb943ace5 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -1,12 +1,14 @@ -Tutorial: Expressions and statements -==================================== +Overflow-prone comparisons in Java +================================== -Overview --------- +You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. -This tutorial develops a query for finding comparisons between integers and long integers in loops that may lead to non-termination due to overflow. +About this article +------------------ -Specifically, consider the following code snippet: +In this tutorial article you'll write a query for finding comparisons between integers and long integers in loops that may lead to non-termination due to overflow. + +To begin, consider this code snippet: .. code-block:: java @@ -24,12 +26,12 @@ If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type `` All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value. -We will develop a query that finds code that looks like it might exhibit this kind of behavior. We will be using several of the standard library classes for representing statements and functions, a full list of which can be found in the :doc:`AST class reference `. +We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions. For a full list, see :doc:`Classes for working with Java code `. Initial query ------------- -We start out by writing a query that finds less-than expressions (CodeQL class ``LTExpr``) where the left operand is of type ``int`` and the right operand is of type ``long``: +We'll start by writing a query that finds less-than expressions (CodeQL class ``LTExpr``) where the left operand is of type ``int`` and the right operand is of type ``long``: .. code-block:: ql @@ -40,9 +42,9 @@ We start out by writing a query that finds less-than expressions (CodeQL class ` expr.getRightOperand().getType().hasName("long") select expr -➤ `See this in the query console `__. This query usually finds results on most projects. +➤ `See this in the query console on LGTM.com `__. This query usually finds results on most projects. -Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks as follows: +Notice that we use the predicate ``getType`` (available on all subclasses of ``Expr``) to determine the type of the operands. Types, in turn, define the ``hasName`` predicate, which allows us to identify the primitive types ``int`` and ``long``. As it stands, this query finds *all* less-than expressions comparing ``int`` and ``long``, but in fact we are only interested in comparisons that are part of a loop condition. Also, we want to filter out comparisons where either operand is constant, since these are less likely to be real bugs. The revised query looks like this: .. code-block:: ql @@ -55,7 +57,7 @@ Notice that we use the predicate ``getType`` (available on all subclasses of ``E not expr.getAnOperand().isCompileTimeConstant() select expr -➤ `See this in the query console `__. Notice that fewer results are found. +➤ `See this in the query console on LGTM.com `__. Notice that fewer results are found. The class ``LoopStmt`` is a common superclass of all loops, including, in particular, ``for`` loops as in our example above. While different kinds of loops have different syntax, they all have a loop condition, which can be accessed through predicate ``getCondition``. We use the reflexive transitive closure operator ``*`` applied to the ``getAChildExpr`` predicate to express the requirement that ``expr`` should be nested inside the loop condition. In particular, it can be the loop condition itself. @@ -78,7 +80,7 @@ In order to compare the ranges of types, we define a predicate that returns the (pt.hasName("long") and result=64) } -We now want to generalize our query to apply to any comparison where the width of the type on the smaller end of the comparison is less than the width of the type on the greater end. Let us call such a comparison *overflow prone*, and introduce an abstract class to model it: +We now want to generalize our query to apply to any comparison where the width of the type on the smaller end of the comparison is less than the width of the type on the greater end. Let's call such a comparison *overflow prone*, and introduce an abstract class to model it: .. code-block:: ql @@ -118,11 +120,11 @@ Now we rewrite our query to make use of these new classes: not expr.getAnOperand().isCompileTimeConstant() select expr -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. -What next? ----------- +Further reading +--------------- -- Have a look at some of the other tutorials: :doc:`Tutorial: Types and the class hierarchy `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Have a look at some of the other articles in this section: :doc:`Java types `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index cf8a2f3c27c..8fd21c2d0c2 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -1,8 +1,10 @@ -Introducing the CodeQL libraries for Java -========================================= +CodeQL library for Java +======================= -Overview --------- +When you're analyzing a Java program in {{ site.data.variables.product.prodname_dotcom }}, you can make use of the large collection of classes in the CodeQL library for Java. + +About the CodeQL library for Java +--------------------------------- There is an extensive library for analyzing CodeQL databases extracted from Java projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. @@ -12,13 +14,13 @@ The library is implemented as a set of QL modules, that is, files with the exten import java -The rest of this topic briefly summarizes the most important classes and predicates provided by this library. +The rest of this article briefly summarizes the most important classes and predicates provided by this library. .. pull-quote:: Note - The example queries in this topic illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The tutorial topics show how you can take a simple query and fine-tune it to find precisely the results you're interested in. + The example queries in this article illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The other articles in this section of the help show how you can take a simple query and fine-tune it to find precisely the results you're interested in. Summary of the library classes ------------------------------ @@ -40,7 +42,7 @@ These classes represent named program elements: packages (``Package``), compilat Their common superclass is ``Element``, which provides general member predicates for determining the name of a program element and checking whether two elements are nested inside each other. -It is often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. +It's often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. Types ~~~~~ @@ -66,9 +68,9 @@ For example, the following query finds all variables of type ``int`` in the prog pt.hasName("int") select v -➤ `See this in the query console `__. You are likely to get many results when you run this query because most projects contain many variables of type ``int``. +➤ `See this in the query console on LGTM.com `__. You're likely to get many results when you run this query because most projects contain many variables of type ``int``. -Reference types can also be categorized according to their declaration scope: +Reference types are also categorized according to their declaration scope: - ``TopLevelType`` represents a reference type declared at the top-level of a compilation unit. - ``NestedType`` is a type declared inside another type. @@ -83,7 +85,7 @@ For instance, this query finds all top-level types whose name is not the same as where tl.getName() != tl.getCompilationUnit().getName() select tl -➤ `See this in the query console `__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code. +➤ `See this in the query console on LGTM.com `__. This pattern is seen in many projects. When we ran it on the LGTM.com demo projects, most of the projects had at least one instance of this problem in the source code. There were many more instances in the files referenced by the source code. Several more specialized classes are available as well: @@ -105,7 +107,7 @@ As an example, we can write a query that finds all nested classes that directly where nc.getASupertype() instanceof TypeObject select nc -➤ `See this in the query console `__. You are likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. +➤ `See this in the query console on LGTM.com `__. You're likely to get many results when you run this query because many projects include nested classes that extend ``Object`` directly. Generics ~~~~~~~~ @@ -139,7 +141,7 @@ For instance, we could use the following query to find all parameterized instanc pt.getSourceDeclaration() = map select pt -➤ `See this in the query console `__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects contain parameterized instances of ``java.util.Map`` in their source code, but they all have results in reference files. In general, generic types may restrict which types a type parameter can be bound to. For instance, a type of maps from strings to numbers could be declared as follows: @@ -162,7 +164,7 @@ As an example, the following query finds all type variables with type bound ``Nu tb.getType().hasQualifiedName("java.lang", "Number") select tv -➤ `See this in the query console `__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *gradle/gradle* and *hibernate/hibernate-orm* projects all contained examples of this pattern. +➤ `See this in the query console on LGTM.com `__. When we ran it on the LGTM.com demo projects, the *neo4j/neo4j*, *gradle/gradle* and *hibernate/hibernate-orm* projects all contained examples of this pattern. For dealing with legacy code that is unaware of generics, every generic type has a "raw" version without any type parameters. In the CodeQL libraries, raw types are represented using class ``RawType``, which has the expected subclasses ``RawClass`` and ``RawInterface``. Again, there is a predicate ``getSourceDeclaration`` for obtaining the corresponding generic type. As an example, we can find variables of (raw) type ``Map``: @@ -175,7 +177,7 @@ For dealing with legacy code that is unaware of generics, every generic type has rt.getSourceDeclaration().hasQualifiedName("java.util", "Map") select v -➤ `See this in the query console `__. Many projects have variables of raw type ``Map``. +➤ `See this in the query console on LGTM.com `__. Many projects have variables of raw type ``Map``. For example, in the following code snippet this query would find ``m1``, but not ``m2``: @@ -194,7 +196,7 @@ The wildcards ``? extends Number`` and ``? super Float`` are represented by clas For dealing with generic methods, there are classes ``GenericMethod``, ``ParameterizedMethod`` and ``RawMethod``, which are entirely analogous to the like-named classes for representing generic types. -More information on working with types can be found in the :doc:`tutorial on types and the class hierarchy `. +For more information on working with types, see the :doc:`article on Java types `. Variables ~~~~~~~~~ @@ -208,7 +210,7 @@ Class ``Variable`` represents a variable `in the Java sense ` for an exhaustive list of all expression and statement types available in the standard QL library. +Classes in this category represent abstract syntax tree (AST) nodes, that is, statements (class ``Stmt``) and expressions (class ``Expr``). For a full list of expression and statement types available in the standard QL library, see :doc:`Classes for working with Java code `. Both ``Expr`` and ``Stmt`` provide member predicates for exploring the abstract syntax tree of a program: @@ -226,7 +228,7 @@ For example, the following query finds all expressions whose parents are ``retur where e.getParent() instanceof ReturnStmt select e -➤ `See this in the query console `__. Many projects have examples of ``return`` statements with child statements. +➤ `See this in the query console on LGTM.com `__. Many projects have examples of ``return`` statements with child statements. Therefore, if the program contains a return statement ``return x + y;``, this query will return ``x + y``. @@ -240,7 +242,7 @@ As another example, the following query finds statements whose parent is an ``if where s.getParent() instanceof IfStmt select s -➤ `See this in the query console `__. Many projects have examples of ``if`` statements with child statements. +➤ `See this in the query console on LGTM.com `__. Many projects have examples of ``if`` statements with child statements. This query will find both ``then`` branches and ``else`` branches of all ``if`` statements in the program. @@ -254,11 +256,11 @@ Finally, here is a query that finds method bodies: where s.getParent() instanceof Method select s -➤ `See this in the query console `__. Most projects have many method bodies. +➤ `See this in the query console on LGTM.com `__. Most projects have many method bodies. As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement. - For more information on working with AST classes, see the :doc:`tutorial on expressions and statements `. +For more information on working with AST classes, see the :doc:`article on overflow-prone comparisons in Java `. Metadata -------- @@ -274,7 +276,7 @@ For annotations, class ``Annotatable`` is a superclass of all program elements t from Constructor c select c.getAnAnnotation() -➤ `See this in the query console `__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all use annotations, you can see examples where they are used to suppress warnings and mark code as deprecated. These annotations are represented by class ``Annotation``. An annotation is simply an expression whose type is an ``AnnotationType``. For example, you can amend this query so that it only reports deprecated constructors: @@ -288,9 +290,9 @@ These annotations are represented by class ``Annotation``. An annotation is simp anntp.hasQualifiedName("java.lang", "Deprecated") select ann -➤ `See this in the query console `__. Only constructors with the ``@deprecated`` annotation are reported this time. +➤ `See this in the query console on LGTM.com `__. Only constructors with the ``@deprecated`` annotation are reported this time. -For more information on working with annotations, see the :doc:`tutorial on annotations `. +For more information on working with annotations, see the :doc:`article on annotations `. For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a delegate ``Documentable`` object, which can then be queried for its attached Javadoc comments. For example, the following query finds Javadoc comments on private fields: @@ -303,7 +305,7 @@ For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a jdoc = f.getDoc().getJavadoc() select jdoc -➤ `See this in the query console `__. You can see this pattern in many projects. +➤ `See this in the query console on LGTM.com `__. You can see this pattern in many projects. Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocElement`` nodes, which can be traversed using member predicates ``getAChild`` and ``getParent``. For instance, you could edit the query so that it finds all ``@author`` tags in Javadoc comments on private fields: @@ -317,7 +319,7 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle at.getParent+() = jdoc select at -➤ `See this in the query console `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. .. pull-quote:: @@ -325,7 +327,7 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle On line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. -For more information on working with Javadoc, see the :doc:`tutorial on Javadoc `. +For more information on working with Javadoc, see the :doc:`article on Javadoc `. Metrics ------- @@ -345,7 +347,7 @@ For example, the following query finds methods with a `cyclomatic complexity 40 select m -➤ `See this in the query console `__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test. +➤ `See this in the query console on LGTM.com `__. Most large projects include some methods with a very high cyclomatic complexity. These methods are likely to be difficult to understand and test. Call graph ---------- @@ -365,7 +367,7 @@ We can use predicate ``Call.getCallee`` to find out which method or constructor m.hasName("println") select c -➤ `See this in the query console `__. The LGTM.com demo projects all include many calls to methods of this name. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all include many calls to methods of this name. Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So we can find methods and constructors that are never called using this query: @@ -377,13 +379,13 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So where not exists(c.getAReference()) select c -➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. +➤ `See this in the query console on LGTM.com `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. -For more information about callables and calls, see the :doc:`call graph tutorial `. +For more information about callables and calls, see the :doc:`article on the call graph `. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the CodeQL for Java tutorial topics: :doc:`Types and the class hierarchy `, :doc:`Expressions and statements `, :doc:`Navigating the call graph `, :doc:`Annotations `, :doc:`Javadoc ` and :doc:`Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Experiment with the worked examples in the CodeQL for Java articles: :doc:`Java types `, :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc ` and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/javadoc.rst b/docs/language/learn-ql/java/javadoc.rst index bd0a11b9132..85981b4bd59 100644 --- a/docs/language/learn-ql/java/javadoc.rst +++ b/docs/language/learn-ql/java/javadoc.rst @@ -1,8 +1,10 @@ -Tutorial: Javadoc -================= +Javadoc +======= -Overview --------- +You can use CodeQL to find errors in Javadoc comments in Java code. + +About analyzing Javadoc +----------------------- To access Javadoc associated with a program element, we use member predicate ``getDoc`` of class ``Element``, which returns a ``Documentable``. Class ``Documentable``, in turn, offers a member predicate ``getJavadoc`` to retrieve the Javadoc attached to the element in question, if any. @@ -49,9 +51,9 @@ The ``JavadocTag`` has several subclasses representing specific kinds of Javadoc Example: Finding spurious @param tags ------------------------------------- -As an example of using the CodeQL Javadoc API, let us write a query that finds ``@param`` tags that refer to a non-existent parameter. +As an example of using the CodeQL Javadoc API, let's write a query that finds ``@param`` tags that refer to a non-existent parameter. -For example, consider the following program: +For example, consider this program: .. code-block:: java @@ -76,7 +78,7 @@ To begin with, we write a query that finds all callables (that is, methods or co where c.getDoc().getJavadoc() = pt.getParent() select c, pt -It is now easy to add another conjunct to the ``where`` clause, restricting the query to ``@param`` tags that refer to a non-existent parameter: we simply need to require that no parameter of ``c`` has the name ``pt.getParamName()``. +It's now easy to add another conjunct to the ``where`` clause, restricting the query to ``@param`` tags that refer to a non-existent parameter: we simply need to require that no parameter of ``c`` has the name ``pt.getParamName()``. .. code-block:: ql @@ -92,7 +94,7 @@ Example: Finding spurious @throws tags A related, but somewhat more involved, problem is finding ``@throws`` tags that refer to an exception that the method in question cannot actually throw. -For example, consider the following Java program: +For example, consider this Java program: .. code-block:: java @@ -108,9 +110,9 @@ For example, consider the following Java program: } } -Notice that the Javadoc comment of ``A.foo`` documents two thrown exceptions: ``IOException`` and ``RuntimeException``. The former is clearly spurious: ``A.foo`` does not have a ``throws IOException`` clause, and thus cannot throw this kind of exception. On the other hand, ``RuntimeException`` is an unchecked exception, so it can be thrown even if there is no explicit ``throws`` clause listing it. Therefore, our query should flag the ``@throws`` tag for ``IOException``, but not the one for ``RuntimeException.`` +Notice that the Javadoc comment of ``A.foo`` documents two thrown exceptions: ``IOException`` and ``RuntimeException``. The former is clearly spurious: ``A.foo`` doesn't have a ``throws IOException`` clause, and therefore can't throw this kind of exception. On the other hand, ``RuntimeException`` is an unchecked exception, so it can be thrown even if there is no explicit ``throws`` clause listing it. So our query should flag the ``@throws`` tag for ``IOException``, but not the one for ``RuntimeException.`` -Recall from above that the CodeQL library represents ``@throws`` tags using class ``ThrowsTag``. This class does not provide a member predicate for determining the exception type that is being documented, so we first need to implement our own version. A simple version might look as follows: +Remember that the CodeQL library represents ``@throws`` tags using class ``ThrowsTag``. This class doesn't provide a member predicate for determining the exception type that is being documented, so we first need to implement our own version. A simple version might look like this: .. code-block:: ql @@ -118,7 +120,7 @@ Recall from above that the CodeQL library represents ``@throws`` tags using clas result.hasName(tt.getExceptionName()) } -Similarly, ``Callable`` does not come with a member predicate for querying all exceptions that the method or constructor may possibly throw. We can, however, implement this ourselves by using ``getAnException`` to find all ``throws`` clauses of the callable, and then use ``getType`` to resolve the corresponding exception types: +Similarly, ``Callable`` doesn't come with a member predicate for querying all exceptions that the method or constructor may possibly throw. We can, however, implement this ourselves by using ``getAnException`` to find all ``throws`` clauses of the callable, and then use ``getType`` to resolve the corresponding exception types: .. code-block:: ql @@ -131,7 +133,7 @@ Note the use of ``getASupertype*`` to find both exceptions declared in a ``throw Now we can write a query for finding all callables ``c`` and ``@throws`` tags ``tt`` such that: - ``tt`` belongs to a Javadoc comment attached to ``c``. -- ``c`` cannot throw the exception documented by ``tt``. +- ``c`` can't throw the exception documented by ``tt``. .. code-block:: ql @@ -145,17 +147,17 @@ Now we can write a query for finding all callables ``c`` and ``@throws`` tags `` not mayThrow(c, exn) select tt, "Spurious @throws tag." -➤ `See this in the query console `__. This finds several results in the LGTM.com demo projects. +➤ `See this in the query console on LGTM.com `__. This finds several results in the LGTM.com demo projects. Improvements ~~~~~~~~~~~~ Currently, there are two problems with this query: -#. ``getDocumentedException`` is too liberal: it will return *any* reference type with the right name, even if it is in a different package and not actually visible in the current compilation unit. -#. ``mayThrow`` is too restrictive: it does not account for unchecked exceptions, which do not need to be declared. +#. ``getDocumentedException`` is too liberal: it will return *any* reference type with the right name, even if it's in a different package and not actually visible in the current compilation unit. +#. ``mayThrow`` is too restrictive: it doesn't account for unchecked exceptions, which do not need to be declared. -To see why the former is a problem, consider the following program: +To see why the former is a problem, consider this program: .. code-block:: java @@ -166,9 +168,9 @@ To see why the former is a problem, consider the following program: void bar() throws IOException {} } -This program defines its own class ``IOException``, which is unrelated to the class ``java.io.IOException`` in the standard library: they are in different packages. Our ``getDocumentedException`` predicate does not check packages, however, so it will consider the ``@throws`` clause to refer to both ``IOException`` classes, and thus flag the ``@param`` tag as spurious, since ``B.bar`` cannot actually throw ``java.io.IOException``. +This program defines its own class ``IOException``, which is unrelated to the class ``java.io.IOException`` in the standard library: they are in different packages. Our ``getDocumentedException`` predicate doesn't check packages, however, so it will consider the ``@throws`` clause to refer to both ``IOException`` classes, and thus flag the ``@param`` tag as spurious, since ``B.bar`` can't actually throw ``java.io.IOException``. -As an example of the second problem, method ``A.foo`` from our previous example was annotated with a ``@throws RuntimeException`` tag. Our current version of ``mayThrow``, however, would think that ``A.foo`` cannot throw a ``RuntimeException``, and thus flag the tag as spurious. +As an example of the second problem, method ``A.foo`` from our previous example was annotated with a ``@throws RuntimeException`` tag. Our current version of ``mayThrow``, however, would think that ``A.foo`` can't throw a ``RuntimeException``, and thus flag the tag as spurious. We can make ``mayThrow`` less restrictive by introducing a new class to represent unchecked exceptions, which are just the subtypes of ``java.lang.RuntimeException`` and ``java.lang.Error``: @@ -196,7 +198,7 @@ Fixing ``getDocumentedException`` is more complicated, but we can easily cover t #. The ``@throws`` tag refers to a type in the same package. #. The ``@throws`` tag refers to a type that is imported by the current compilation unit. -The first case can be covered by changing ``getDocumentedException`` to use the qualified name of the ``@throws`` tag. To handle the second and the third case, we can introduce a new predicate ``visibleIn`` that checks whether a reference type is visible in a compilation unit, either by virtue of belonging to the same package or by being explicitly imported. We then rewrite ``getDocumentedException`` as follows: +The first case can be covered by changing ``getDocumentedException`` to use the qualified name of the ``@throws`` tag. To handle the second and the third case, we can introduce a new predicate ``visibleIn`` that checks whether a reference type is visible in a compilation unit, either by virtue of belonging to the same package or by being explicitly imported. We then rewrite ``getDocumentedException`` as: .. code-block:: ql @@ -212,13 +214,13 @@ The first case can be covered by changing ``getDocumentedException`` to use the (result.hasName(tt.getExceptionName()) and visibleIn(tt.getFile(), result)) } -➤ `See this in the query console `__. This finds many fewer, more interesting results in the LGTM.com demo projects. +➤ `See this in the query console on LGTM.com `__. This finds many fewer, more interesting results in the LGTM.com demo projects. -Currently, ``visibleIn`` only considers single-type imports, but it would be possible to extend it with support for other kinds of imports. +Currently, ``visibleIn`` only considers single-type imports, but you could extend it with support for other kinds of imports. -What next? ----------- +Further reading +--------------- -- Find out how you can use the location API to define queries on whitespace: :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out how you can use the location API to define queries on whitespace: :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/ql-for-java.rst b/docs/language/learn-ql/java/ql-for-java.rst index aa26c5ba6bb..3b5b64dd99b 100644 --- a/docs/language/learn-ql/java/ql-for-java.rst +++ b/docs/language/learn-ql/java/ql-for-java.rst @@ -1,8 +1,9 @@ CodeQL for Java =============== +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java codebases. + .. toctree:: - :glob: :hidden: introduce-libraries-java @@ -15,29 +16,28 @@ CodeQL for Java source-locations ast-class-reference -These topics provide an overview of the CodeQL libraries for Java and show examples of how to use them. +- `Basic Java query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic Java query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for Java `: When analyzing Java code, you can use the large collection of classes in the CodeQL library for Java. -- :doc:`Introducing the CodeQL libraries for Java ` introduces the standard libraries used to write queries for Java code. +- :doc:`Analyzing data flow in Java `: You can use CodeQL to track the flow of data through a Java program to its use. -- :doc:`Tutorial: Analyzing data flow in Java ` demonstrates how to write queries using the standard data flow and taint tracking libraries for Java. +- :doc:`Java types `: You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. -- :doc:`Tutorial: Types and the class hierarchy ` introduces the classes for representing a program's class hierarchy by means of examples. +- :doc:`Overflow-prone comparisons in Java `: You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow. -- :doc:`Tutorial: Expressions and statements ` introduces the classes for representing a program's syntactic structure by means of examples. +- :doc:`Navigating the call graph `: CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used. -- :doc:`Tutorial: Navigating the call graph ` is a worked example of how to write a query that navigates a program's call graph to find unused methods. +- :doc:`Annotations in Java `: CodeQL databases of Java projects contain information about all annotations attached to program elements. -- :doc:`Tutorial: Annotations ` introduces the classes for representing annotations by means of examples. +- :doc:`Javadoc `: You can use CodeQL to find errors in Javadoc comments in Java code. -- :doc:`Tutorial: Javadoc ` introduces the classes for representing Javadoc comments by means of examples. +- :doc:`Working with source locations `: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. -- :doc:`Tutorial: Working with source locations ` is a worked example of how to write a query that uses the location information provided in the database for finding likely bugs. +- :doc:`Classes for working with Java code `: CodeQL has a large selection of classes for working with Java statements and expressions. -- :doc:`AST class reference ` gives an overview of all AST classes in the standard CodeQL library for Java. -Other resources +Further reading --------------- - For examples of how to query common Java elements, see the `Java cookbook `__. diff --git a/docs/language/learn-ql/java/source-locations.rst b/docs/language/learn-ql/java/source-locations.rst index 6e29777fab9..7d3506b3923 100644 --- a/docs/language/learn-ql/java/source-locations.rst +++ b/docs/language/learn-ql/java/source-locations.rst @@ -1,10 +1,12 @@ -Tutorial: Working with source locations -======================================= +Working with source locations +============================= -Overview --------- +You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem. -Java offers a rich set of operators with complex precedence rules, which are sometimes confusing to developers. For instance, the class ``ByteBufferCache`` in the OpenJDK Java compiler (which is a member class of ``com.sun.tools.javac.util.BaseFileManager``) contains the following code for allocating a buffer: +About source locations +---------------------- + +Java offers a rich set of operators with complex precedence rules, which are sometimes confusing to developers. For instance, the class ``ByteBufferCache`` in the OpenJDK Java compiler (which is a member class of ``com.sun.tools.javac.util.BaseFileManager``) contains this code for allocating a buffer: .. code-block:: java @@ -14,14 +16,14 @@ Presumably, the author meant to allocate a buffer that is 1.5 times the size ind Note that the source layout gives a fairly clear indication of the intended meaning: there is more white space around ``+`` than around ``>>``, suggesting that the latter is meant to bind more tightly. -We will now develop a query that finds this kind of suspicious nesting, where the operator of the inner expression has more white space around it than the operator of the outer expression. This pattern may not necessarily indicate a bug, but at the very least it makes the code hard to read and prone to misinterpretation. +We're going to develop a query that finds this kind of suspicious nesting, where the operator of the inner expression has more white space around it than the operator of the outer expression. This pattern may not necessarily indicate a bug, but at the very least it makes the code hard to read and prone to misinterpretation. -White space is not directly represented in the CodeQL database, but we can deduce its presence from the location information associated with program elements and AST nodes. So we will start by providing an overview of source location management in the standard library for Java. +White space is not directly represented in the CodeQL database, but we can deduce its presence from the location information associated with program elements and AST nodes. So, before we write our query, we need an understanding of source location management in the standard library for Java. Location API ------------ -For every entity that has a representation in Java source code (including, in particular, program elements and AST nodes), the standard CodeQL library provides the following predicates for accessing source location information: +For every entity that has a representation in Java source code (including, in particular, program elements and AST nodes), the standard CodeQL library provides these predicates for accessing source location information: - ``getLocation`` returns a ``Location`` object describing the start and end position of the entity. - ``getFile`` returns a ``File`` object representing the file containing the entity. @@ -29,7 +31,7 @@ For every entity that has a representation in Java source code (including, in pa - ``getNumberOfCommentLines`` returns the number of comment lines. - ``getNumberOfLinesOfCode`` returns the number of non-comment lines. -For example, assume the following Java class is defined in compilation unit ``SayHello.java``: +For example, let's assume this Java class is defined in the compilation unit ``SayHello.java``: .. code-block:: java @@ -44,20 +46,20 @@ For example, assume the following Java class is defined in compilation unit ``Sa } } -Invoking ``getFile`` on the expression statement in the body of ``main`` will return a ``File`` object representing the file ``SayHello.java``. The statement spans four lines in total ``(getTotalNumberOfLines``), of which one is a comment line (``getNumberOfCommentLines``), while three lines contain code (``getNumberOfLinesOfCode``). +Invoking ``getFile`` on the expression statement in the body of ``main`` returns a ``File`` object representing the file ``SayHello.java``. The statement spans four lines in total ``(getTotalNumberOfLines``), of which one is a comment line (``getNumberOfCommentLines``), while three lines contain code (``getNumberOfLinesOfCode``). Class ``Location`` defines member predicates ``getStartLine``, ``getEndLine``, ``getStartColumn`` and ``getEndColumn`` to retrieve the line and column number an entity starts and ends at, respectively. Both lines and columns are counted starting from 1 (not 0), and the end position is inclusive, that is, it is the position of the last character belonging to the source code of the entity. In our example, the expression statement starts at line 5, column 3 (the first two characters on the line are tabs, which each count as one character), and it ends at line 8, column 4. -Class ``File`` defines the following member predicates: +Class ``File`` defines these member predicates: - ``getFullName`` returns the fully qualified name of the file. - ``getRelativePath`` returns the path of the file relative to the base directory of the source code. - ``getExtension`` returns the extension of the file. - ``getShortName`` returns the base name of the file, without its extension. -In our example, assume file ``A.java`` is located in directory ``/home/testuser/code/pkg``, where ``/home/testuser/code`` is the base directory of the program being analyzed. Then, a ``File`` object for ``A.java`` returns the following: +In our example, assume file ``A.java`` is located in directory ``/home/testuser/code/pkg``, where ``/home/testuser/code`` is the base directory of the program being analyzed. Then, a ``File`` object for ``A.java`` returns: - ``getFullName`` is ``/home/testuser/code/pkg/A.java``. - ``getRelativePath`` is ``pkg/A.java``. @@ -67,7 +69,7 @@ In our example, assume file ``A.java`` is located in directory ``/home/testuser/ Determining white space around an operator ------------------------------------------ -Let us start by considering how to write a predicate that computes the total amount of white space surrounding the operator of a given binary expression. If ``rcol`` is the start column of the expression's right operand and ``lcol`` is the end column of its left operand, then ``rcol - (lcol+1)`` gives us the total number of characters in between the two operands (note that we have to use ``lcol+1`` instead of ``lcol`` because end positions are inclusive). +Let's start by considering how to write a predicate that computes the total amount of white space surrounding the operator of a given binary expression. If ``rcol`` is the start column of the expression's right operand and ``lcol`` is the end column of its left operand, then ``rcol - (lcol+1)`` gives us the total number of characters in between the two operands (note that we have to use ``lcol+1`` instead of ``lcol`` because end positions are inclusive). This number includes the length of the operator itself, which we need to subtract out. For this, we can use predicate ``getOp``, which returns the operator string, surrounded by one white space on either side. Overall, the expression for computing the amount of white space around the operator of a binary expression ``expr`` is: @@ -88,12 +90,12 @@ Clearly, however, this only works if the entire expression is on a single line, ) } -Notice that we use an ``exists`` to introduce our temporary variables ``lcol`` and ``rcol``. The predicate could be written without them by just inlining ``lcol`` and ``rcol`` into their use, at some cost in readability. +Notice that we use an ``exists`` to introduce our temporary variables ``lcol`` and ``rcol``. You could write the predicate without them by just inlining ``lcol`` and ``rcol`` into their use, at some cost in readability. Find suspicious nesting ----------------------- -A first version of our query can now be written: +Here's a first version of our query: .. code-block:: ql @@ -108,7 +110,7 @@ A first version of our query can now be written: wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. This query is likely to find results on most projects. +➤ `See this in the query console on LGTM.com `__. This query is likely to find results on most projects. The first conjunct of the ``where`` clause restricts ``inner`` to be an operand of ``outer``, the second conjunct binds ``wsinner`` and ``wsouter``, while the last conjunct selects the suspicious cases. @@ -123,7 +125,7 @@ If we run this initial query, we might notice some false positives arising from i< start + 100 -Note that our predicate ``operatorWS`` computes the **total** amount of white space around the operator, which, in this case, is one for the ``<`` and two for the ``+``. Ideally, we would like to exclude cases where the amount of white space before and after the operator are not the same. Currently, CodeQL databases do not record enough information to figure this out, but as an approximation we could require that the total number of white space characters is even: +Note that our predicate ``operatorWS`` computes the **total** amount of white space around the operator, which, in this case, is one for the ``<`` and two for the ``+``. Ideally, we would like to exclude cases where the amount of white space before and after the operator are not the same. Currently, CodeQL databases don't record enough information to figure this out, but as an approximation we could require that the total number of white space characters is even: .. code-block:: ql @@ -139,7 +141,7 @@ Note that our predicate ``operatorWS`` computes the **total** amount of white sp wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. Any results will be refined by our changes to the query. +➤ `See this in the query console on LGTM.com `__. Any results will be refined by our changes to the query. Another source of false positives are associative operators: in an expression of the form ``x + y+z``, the first plus is syntactically nested inside the second, since + in Java associates to the left; hence the expression is flagged as suspicious. But since + is associative to begin with, it does not matter which way around the operators are nested, so this is a false positive.To exclude these cases, let us define a new class identifying binary expressions with an associative operator: @@ -171,7 +173,7 @@ Now we can extend our query to discard results where the outer and the inner exp wsinner > wsouter select outer, "Whitespace around nested operators contradicts precedence." -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Notice that we again use ``getOp``, this time to determine whether two binary expressions have the same operator. Running our improved query now finds the Java standard library bug described in the Overview. It also flags up the following suspicious code in `Hadoop HBase `__: @@ -181,8 +183,8 @@ Notice that we again use ``getOp``, this time to determine whether two binary ex Whitespace suggests that the programmer meant to toggle ``i`` between zero and one, but in fact the expression is parsed as ``i + (1%2)``, which is the same as ``i + 1``, so ``i`` is simply incremented. -What next? ----------- +Further reading +--------------- -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index a438f111cab..3cdafa8389a 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -1,8 +1,10 @@ -Tutorial: Types and the class hierarchy -======================================= +Java types +========== -Overview --------- +You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues. + +About working with Java types +----------------------------- The standard CodeQL library represents Java types by means of the ``Type`` class and its various subclasses. @@ -30,7 +32,7 @@ To determine ancestor types (including immediate super types, and also *their* s where B.hasName("B") select B.getASupertype+() -➤ `See this in the query console `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. +➤ `See this in the query console on LGTM.com `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. .. pull-quote:: @@ -59,7 +61,7 @@ If the expression ``e`` happens to actually evaluate to a ``B[]`` array, on the Object[] o = new String[] { "Hello", "world" }; String[] s = (String[])o; -In this tutorial, we do not try to distinguish these two cases. Our query should simply look for cast expressions ``ce`` that cast from some type ``source`` to another type ``target``, such that: +In this tutorial, we don't try to distinguish these two cases. Our query should simply look for cast expressions ``ce`` that cast from some type ``source`` to another type ``target``, such that: - Both ``source`` and ``target`` are array types. - The element type of ``source`` is a transitive super type of the element type of ``target``. @@ -76,7 +78,7 @@ This recipe is not too difficult to translate into a query: target.getElementType().(RefType).getASupertype+() = source.getElementType() select ce, "Potentially problematic array downcast." -➤ `See this in the query console `__. Many projects return results for this query. +➤ `See this in the query console on LGTM.com `__. Many projects return results for this query. Note that by casting ``target.getElementType()`` to a ``RefType``, we eliminate all cases where the element type is a primitive type, that is, ``target`` is an array of primitive type: the problem we are looking for cannot arise in that case. Unlike in Java, a cast in QL never fails: if an expression cannot be cast to the desired type, it is simply excluded from the query results, which is exactly what we want. @@ -139,12 +141,12 @@ Using these new classes we can extend our query to exclude calls to ``toArray`` not ce.getExpr().(CollectionToArrayCall).getActualReturnType() = target select ce, "Potentially problematic array downcast." -➤ `See this in the query console `__. Notice that fewer results are found by this improved query. +➤ `See this in the query console on LGTM.com `__. Notice that fewer results are found by this improved query. Example: Finding mismatched contains checks ------------------------------------------- -As another example, we develop a query that finds uses of ``Collection.contains`` where the type of the queried element is unrelated to the element type of the collection, thus guaranteeing that the test will always return ``false``. +We'll now develop a query that finds uses of ``Collection.contains`` where the type of the queried element is unrelated to the element type of the collection, which guarantees that the test will always return ``false``. For example, `Apache Zookeeper `__ used to have a snippet of code similar to the following in class ``QuorumPeerConfig``: @@ -265,14 +267,14 @@ Now we are ready to write a first version of our query: not haveCommonDescendant(collEltType, argType) select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Improvements ~~~~~~~~~~~~ For many programs, this query yields a large number of false positive results due to type variables and wild cards: if the collection element type is some type variable ``E`` and the argument type is ``String``, for example, CodeQL will consider that the two have no common subtype, and our query will flag the call. An easy way to exclude such false positive results is to simply require that neither ``collEltType`` nor ``argType`` are instances of ``TypeVariable``. -Another source of false positives is autoboxing of primitive types: if, for example, the collection's element type is ``Integer`` and the argument is of type ``int``, predicate ``haveCommonDescendant`` will fail, since ``int`` is not a ``RefType``. Thus, our query should check that ``collEltType`` is not the boxed type of ``argType``. +Another source of false positives is autoboxing of primitive types: if, for example, the collection's element type is ``Integer`` and the argument is of type ``int``, predicate ``haveCommonDescendant`` will fail, since ``int`` is not a ``RefType``. To account for this, our query should check that ``collEltType`` is not the boxed type of ``argType``. Finally, ``null`` is special because its type (known as ```` in the CodeQL library) is compatible with every reference type, so we should exclude it from consideration. @@ -292,11 +294,11 @@ Adding these three improvements, our final query becomes: not argType.hasName("") select juccc, "Element type " + collEltType + " is incompatible with argument type " + argType -➤ `See the full query in the query console `__. +➤ `See the full query in the query console on LGTM.com `__. -What next? ----------- +Further reading +--------------- -- Take a look at some of the other tutorials: :doc:`Tutorial: Expressions and statements `, :doc:`Tutorial: Navigating the call graph `, :doc:`Tutorial: Annotations `, :doc:`Tutorial: Javadoc `, and :doc:`Tutorial: Working with source locations `. -- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`AST class reference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Take a look at some of the other articles in this section: :doc:`Overflow-prone comparisons in Java `, :doc:`Navigating the call graph `, :doc:`Annotations in Java `, :doc:`Javadoc `, and :doc:`Working with source locations `. +- Find out how specific classes in the AST are represented in the standard library for Java: :doc:`Classes for working with Java code `. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/javascript/ast-class-reference.rst b/docs/language/learn-ql/javascript/ast-class-reference.rst index 1b513b2d4ec..f0a7f88fc17 100644 --- a/docs/language/learn-ql/javascript/ast-class-reference.rst +++ b/docs/language/learn-ql/javascript/ast-class-reference.rst @@ -1,5 +1,7 @@ -AST class reference -=================== +Abstract syntax tree classes for JavaScript and TypeScript +========================================================== + +CodeQL has a large selection of classes for working with JavaScript and TypeScript statements and expressions. Statement classes ----------------- diff --git a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst index a2ff4309ee0..a78dc116e37 100644 --- a/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst +++ b/docs/language/learn-ql/javascript/dataflow-cheat-sheet.rst @@ -1,7 +1,7 @@ -Data flow cheat sheet -===================== +Data flow cheat sheet for JavaScript +==================================== -This page describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. +This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. Taint tracking path queries --------------------------- @@ -34,12 +34,12 @@ This query reports flow paths which: - Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep `__. - End at a node matched by `isSink `__. -See also: `Global data flow `__ and :doc:`Constructing path queries <../writing-queries/path-queries>`. +See also: `Global data flow `__ and :doc:`Creating path queries <../writing-queries/path-queries>`. DataFlow module --------------- -Use data flow nodes to match program elements independently of syntax. See also: :doc:`Analyzing data flow in JavaScript/TypeScript `. +Use data flow nodes to match program elements independently of syntax. See also: :doc:`Analyzing data flow in JavaScript and TypeScript `. Predicates in the ``DataFlow::`` module: @@ -142,7 +142,7 @@ Files AST nodes --------- -See also: :doc:`AST class reference `. +See also: :doc:`Abstract syntax tree classes for JavaScript and TypeScript `. Conversion between DataFlow and AST nodes: @@ -163,7 +163,7 @@ String matching Type tracking ------------- -See also: :doc:`Type tracking tutorial `. +See also: :doc:`Using type tracking for API modeling `. Use the following template to define forward type tracking predicates: diff --git a/docs/language/learn-ql/javascript/dataflow.rst b/docs/language/learn-ql/javascript/dataflow.rst index 15cd1ad7e46..5009db4756a 100644 --- a/docs/language/learn-ql/javascript/dataflow.rst +++ b/docs/language/learn-ql/javascript/dataflow.rst @@ -1,16 +1,15 @@ Analyzing data flow in JavaScript and TypeScript ================================================ +This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. + Overview -------- - -This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. -The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking. - +The various sections in this article describe how to utilize the libraries for local data flow, global data flow, and taint tracking. As our running example, we will develop a query that identifies command-line arguments that are passed as a file path to the standard Node.js ``readFile`` function. While this is not a problematic pattern as such, it is typical of the kind of reasoning that is frequently used in security queries. -For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`. +For a more general introduction to modeling data flow, see :doc:`About data flow analysis <../intro-to-data-flow>`. Data flow nodes --------------- @@ -465,12 +464,12 @@ Hint: array indices are properties with numeric names; you can use regular expre Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from array elements of the result of a call to the ``tagName`` argument to the ``createElement`` function. (`Answer <#exercise-4>`__) -What next? ----------- +Further reading +--------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. -- Learn about writing more precise data-flow analyses in :doc:`Advanced data-flow analysis using flow labels ` +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. +- Learn about writing more precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis ` Answers ------- diff --git a/docs/language/learn-ql/javascript/flow-labels.rst b/docs/language/learn-ql/javascript/flow-labels.rst index c693319576d..ecd8dec6b29 100644 --- a/docs/language/learn-ql/javascript/flow-labels.rst +++ b/docs/language/learn-ql/javascript/flow-labels.rst @@ -1,8 +1,13 @@ -Tutorial: Precise data-flow analysis using flow labels -====================================================== +Using flow labels for precise data flow analysis +================================================ + +You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. + +Overview +-------- You can use basic inter-procedural data-flow analysis and taint tracking as described in -:doc:`Analyzing data flow in JavaScript/TypeScript ` to check whether there is a path in +:doc:`Analyzing data flow in JavaScript and TypeScript ` to check whether there is a path in the data-flow graph from some source node to a sink node that does not pass through any sanitizer nodes. Another way of thinking about this is that it statically models the flow of data through the program, and associates a flag with every data value telling us whether it might have come from a @@ -390,9 +395,9 @@ tainted objects from partially tainted objects. The `Uncontrolled data used in p `_ query uses four flow labels to track whether a user-controlled string may be an absolute path and whether it may contain ``..`` components. -What next? ----------- +Further reading +--------------- -- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`Introducing the JavaScript libraries `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index f01a8387a18..65b19f2687d 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -1,5 +1,7 @@ -Introducing the CodeQL libraries for JavaScript -=============================================== +CodeQL library for JavaScript +============================= + +When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript. Overview -------- @@ -73,7 +75,7 @@ For example, the following query computes, for each folder, the number of JavaSc from Folder d select d.getRelativePath(), count(File f | f = d.getAFile() and f.getExtension() = "js") -➤ `See this in the query console `__. When you run the query on most projects, the results include folders that contain files with a ``js`` extension and folders that don't. +➤ `See this in the query console on LGTM.com `__. When you run the query on most projects, the results include folders that contain files with a ``js`` extension and folders that don't. Locations ^^^^^^^^^ @@ -134,7 +136,7 @@ As an example of a query operating entirely on the lexical level, consider the f where comma.getNextToken() instanceof CommaToken select comma, "Omitted array elements are bad style." -➤ `See this in the query console `__. If the query returns no results, this pattern isn't used in the projects that you analyzed. +➤ `See this in the query console on LGTM.com `__. If the query returns no results, this pattern isn't used in the projects that you analyzed. You can use predicate ``Locatable.getFirstToken()`` and ``Locatable.getLastToken()`` to access the first and last token (if any) belonging to an element with a source location. @@ -175,7 +177,7 @@ As an example of a query using only lexical information, consider the following from HtmlLineComment c select c, "Do not use HTML comments." -➤ `See this in the query console `__. When we ran this query on the *mozilla/pdf.js* project in LGTM.com, we found three HTML comments. +➤ `See this in the query console on LGTM.com `__. When we ran this query on the *mozilla/pdf.js* project in LGTM.com, we found three HTML comments. Syntactic level ~~~~~~~~~~~~~~~ @@ -347,7 +349,7 @@ As an example of how to use expression AST nodes, here is a query that finds exp where add = shift.getAnOperand() select add, "This expression should be bracketed to clarify precedence rules." -➤ `See this in the query console `__. When we ran this query on the *meteor/meteor* project in LGTM.com, we found many results where precedence could be clarified using brackets. +➤ `See this in the query console on LGTM.com `__. When we ran this query on the *meteor/meteor* project in LGTM.com, we found many results where precedence could be clarified using brackets. Functions ^^^^^^^^^ @@ -369,7 +371,7 @@ As an example, here is a query that finds all expression closures: where fe.getBody() instanceof Expr select fe, "Use arrow expressions instead of expression closures." -➤ `See this in the query console `__. None of the LGTM.com demo projects uses expression closures, but you may find this query gets results on other projects. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects uses expression closures, but you may find this query gets results on other projects. As another example, this query finds functions that have two parameters that bind the same variable: @@ -384,7 +386,7 @@ As another example, this query finds functions that have two parameters that bin p.getAVariable() = q.getAVariable() select fun, "This function has two parameters that bind the same variable." -➤ `See this in the query console `__. None of the LGTM.com demo projects has functions where two parameters bind the same variable. +➤ `See this in the query console on LGTM.com `__. None of the LGTM.com demo projects has functions where two parameters bind the same variable. Classes ^^^^^^^ @@ -440,7 +442,7 @@ Here is an example of a query to find declaration statements that declare the sa not ds.getTopLevel().isMinified() select ds, "Variable " + v.getName() + " is declared both $@ and $@.", d1, "here", d2, "here" -➤ `See this in the query console `__. This is not a common problem, so you may not find any results in your own projects. The *angular/angular.js* project on LGTM.com has one instance of this problem at the time of writing. +➤ `See this in the query console on LGTM.com `__. This is not a common problem, so you may not find any results in your own projects. The *angular/angular.js* project on LGTM.com has one instance of this problem at the time of writing. Notice the use of ``not ... isMinified()`` here and in the next few queries. This excludes any results found in minified code. If you delete ``and not ds.getTopLevel().isMinified()`` and re-run the query, two results in minified code in the *meteor/meteor* project are reported. @@ -467,7 +469,7 @@ As an example of a query involving properties, consider the following query that not oe.getTopLevel().isMinified() select oe, "Property " + p1.getName() + " is defined both $@ and $@.", p1, "here", p2, "here" -➤ `See this in the query console `__. Many projects have a few instances of object expressions with two identically named properties. +➤ `See this in the query console on LGTM.com `__. Many projects have a few instances of object expressions with two identically named properties. Modules ^^^^^^^ @@ -533,7 +535,7 @@ As an example, consider the following query which finds distinct function declar not g.getTopLevel().isMinified() select f, g -➤ `See this in the query console `__. Some projects declare conflicting functions of the same name and rely on platform-specific behavior to disambiguate the two declarations. +➤ `See this in the query console on LGTM.com `__. Some projects declare conflicting functions of the same name and rely on platform-specific behavior to disambiguate the two declarations. Control flow ~~~~~~~~~~~~ @@ -570,7 +572,7 @@ As an example of an analysis using basic blocks, ``BasicBlock.isLiveAtEntry(v, u not f.getStartBB().isLiveAtEntry(gv, _) select f, "This function uses " + gv + " like a local variable." -➤ `See this in the query console `__. Many projects have some variables which look as if they were intended to be local. +➤ `See this in the query console on LGTM.com `__. Many projects have some variables which look as if they were intended to be local. Data flow ~~~~~~~~~ @@ -595,7 +597,7 @@ As an example, the following query finds definitions of local variables that are not exists (VarUse use | def = use.getADef()) select def, "Dead store of local variable." -➤ `See this in the query console `__. Many projects have some examples of useless assignments to local variables. +➤ `See this in the query console on LGTM.com `__. Many projects have some examples of useless assignments to local variables. SSA ^^^ @@ -638,7 +640,7 @@ For example, here is a query that finds all invocations of a method called ``sen send.getMethodName() = "send" select send -➤ `See this in the query console `__. The query finds HTTP response sends in the `AMP HTML `__ project. +➤ `See this in the query console on LGTM.com `__. The query finds HTTP response sends in the `AMP HTML `__ project. Note that the data flow modeling in this library is intraprocedural, that is, flow across function calls and returns is *not* modeled. Likewise, flow through object properties and global variables is not modeled. @@ -703,7 +705,7 @@ As an example of a call-graph-based query, here is a query to find invocations f not exists(invk.getACallee()) select invk, "Unable to find a callee for this invocation." -➤ `See this in the query console `__ +➤ `See this in the query console on LGTM.com `__ Inter-procedural data flow ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -839,7 +841,7 @@ As an example of the use of these classes, here is a query that counts for every from NodeModule m select m, count(m.getAnImportedModule()) -➤ `See this in the query console `__. When you analyze a project, for each module you can see how many other modules it imports. +➤ `See this in the query console on LGTM.com `__. When you analyze a project, for each module you can see how many other modules it imports. NPM ^^^ @@ -868,7 +870,7 @@ As an example of the use of these classes, here is a query that identifies unuse not exists (Require req | req.getTopLevel() = pkg.getAModule() | name = req.getImportedPath().getValue()) select deps, "Unused dependency '" + name + "'." -➤ `See this in the query console `__. It is not uncommon for projects to have some unused dependencies. +➤ `See this in the query console on LGTM.com `__. It is not uncommon for projects to have some unused dependencies. React ^^^^^ @@ -895,7 +897,7 @@ For example, here is a query to find SQL queries that use string concatenation ( where ss instanceof AddExpr select ss, "Use templating instead of string concatenation." -➤ `See this in the query console `__, showing two (benign) results on `strong-arc `__. +➤ `See this in the query console on LGTM.com `__, showing two (benign) results on `strong-arc `__. Miscellaneous ~~~~~~~~~~~~~ @@ -961,7 +963,7 @@ As an example, here is a query that finds ``@param`` tags that do not specify th not exists(t.getName()) select t, "@param tag is missing name." -➤ `See this in the query console `__. Of the LGTM.com demo projects analyzed, only *Semantic-Org/Semantic-UI* has an example where the ``@param`` tag omits the name. +➤ `See this in the query console on LGTM.com `__. Of the LGTM.com demo projects analyzed, only *Semantic-Org/Semantic-UI* has an example where the ``@param`` tag omits the name. For full details on these and other classes representing JSDoc comments and type expressions, see `the API documentation `__. @@ -1026,9 +1028,9 @@ Alias nodes are represented by class `YAMLAliasNode `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. +- Learn about the standard CodeQL libraries used to write queries for TypeScript in :doc:`CodeQL libraries for TypeScript `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index e0c1ec748ff..672ea369479 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -1,5 +1,7 @@ -Introducing the CodeQL libraries for TypeScript -=============================================== +CodeQL library for TypeScript +============================= + +When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript. Overview -------- @@ -10,7 +12,7 @@ Support for analyzing TypeScript code is bundled with the CodeQL libraries for J import javascript -The :doc:`CodeQL library introduction for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. +:doc:`CodeQL libraries for JavaScript ` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates. Syntax ------ @@ -119,7 +121,7 @@ Select expressions that cast a value to a type parameter: where assertion.getTypeAnnotation() = param.getLocalTypeName().getAnAccess() select assertion, "Cast to type parameter." -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Classes and interfaces ~~~~~~~~~~~~~~~~~~~~~~ @@ -134,7 +136,7 @@ The CodeQL class `ClassOrInterface `__. -Also see the documentation for classes in the `Introduction to the CodeQL libraries for JavaScript `__. +Also see the documentation for classes in the `CodeQL libraries for JavaScript `__. To select the type references to a class or an interface, use ``getTypeName()``. @@ -405,7 +407,7 @@ It is best to use `TypeName `__. +➤ `See this in the query console on LGTM.com `__. Find imported names that are used as both a type and a value: @@ -418,7 +420,7 @@ Find imported names that are used as both a type and a value: and exists (VarAccess access | access.getVariable().getADeclaration() = spec.getLocal()) select spec, "Used as both variable and type" -➤ `See this in the query console `__. +➤ `See this in the query console on LGTM.com `__. Namespace names ~~~~~~~~~~~~~~~ @@ -444,9 +446,9 @@ A `LocalNamespaceName `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. \ No newline at end of file +- Learn about the standard CodeQL libraries used to write queries for JavaScript in :doc:`CodeQL libraries for JavaScript `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. diff --git a/docs/language/learn-ql/javascript/ql-for-javascript.rst b/docs/language/learn-ql/javascript/ql-for-javascript.rst index d2d864cc072..5e10e9f979d 100644 --- a/docs/language/learn-ql/javascript/ql-for-javascript.rst +++ b/docs/language/learn-ql/javascript/ql-for-javascript.rst @@ -1,8 +1,9 @@ CodeQL for JavaScript ===================== +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from JavaScript codebases. + .. toctree:: - :glob: :hidden: introduce-libraries-js @@ -13,23 +14,23 @@ CodeQL for JavaScript ast-class-reference dataflow-cheat-sheet -These documents provide an overview of the CodeQL libraries for JavaScript and TypeScript and show examples of how to use them. +- `Basic JavaScript query `__: Learn to write and run a simple CodeQL query using LGTM. -- `Basic JavaScript query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for JavaScript `: When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript. -- :doc:`Introducing the CodeQL libraries for JavaScript ` introduces the standard libraries used to write queries for JavaScript code. There is an extensive CodeQL library for analyzing JavaScript code. This tutorial briefly summarizes the most important classes and predicates provided by this library. +- :doc:`CodeQL library for TypeScript `: When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript. -- :doc:`Introducing the CodeQL libraries for TypeScript ` introduces the standard libraries used to write queries for TypeScript code. +- :doc:`Analyzing data flow in JavaScript and TypeScript `: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries. -- :doc:`Analyzing data flow in JavaScript/TypeScript ` demonstrates how to write queries using the standard data flow and taint tracking libraries for JavaScript/TypeScript. +- :doc:`Using flow labels for precise data flow analysis `: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities. -- :doc:`Advanced data-flow analysis using flow labels ` shows a more advanced example of data flow analysis using flow labels. +- :doc:`Using type tracking for API modeling `: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. -- :doc:`AST class reference ` gives an overview of all AST classes in the standard CodeQL library for JavaScript. +- :doc:`Abstract syntax tree classes for JavaScript and TypeScript `: CodeQL has a large selection of classes for working with JavaScript and TypeScript statements and expressions. -- :doc:`Data flow cheat sheet ` lists parts of the CodeQL libraries that are commonly used for variant analysis and in data flow queries. +- :doc:`Data flow cheat sheet for JavaScript `: This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries. -Other resources +Further reading --------------- - For examples of how to query common JavaScript elements, see the `JavaScript cookbook `__. diff --git a/docs/language/learn-ql/javascript/type-tracking.rst b/docs/language/learn-ql/javascript/type-tracking.rst index f0dadd9ef70..d192d98472e 100644 --- a/docs/language/learn-ql/javascript/type-tracking.rst +++ b/docs/language/learn-ql/javascript/type-tracking.rst @@ -1,9 +1,10 @@ -Tutorial: API modelling using type tracking -=========================================== +Using type tracking for API modeling +==================================== -This tutorial demonstrates how to build a simple model of the Firebase API -using the CodeQL type-tracking library for JavaScript. +You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript. +Overview +-------- The type-tracking library makes it possible to track values through properties and function calls, usually to recognize method calls and properties accessed on a specific type of object. @@ -489,7 +490,7 @@ Prefer type tracking when: Prefer data-flow configurations when: - Tracking user-controlled data -- use `taint tracking `__. -- Differentiating between different kinds of user-controlled data -- use :doc:`flow labels `. +- Differentiating between different kinds of user-controlled data -- see :doc:`Using flow labels for precise data flow analysis `. - Tracking transformations of a value through generic utility functions. - Tracking values through string manipulation. - Generating a path from source to sink -- see :doc:`constructing path queries <../writing-queries/path-queries>`. @@ -517,9 +518,9 @@ Type tracking is used in a few places in the standard libraries: - The `Firebase `__ and `Socket.io `__ models use type tracking to track objects coming from their respective APIs. -What next? ----------- +Further reading +--------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Learn more about the query console in `Using the query console `__. -- Learn about writing precise data-flow analyses in :doc:`Advanced data-flow analysis using flow labels `. +- Find out more about QL in the `QL language reference `__. +- Learn more about the query console in `Using the query console `__ on LGTM.com. +- Learn about writing precise data-flow analyses in :doc:`Using flow labels for precise data flow analysis `. diff --git a/docs/language/learn-ql/locations.rst b/docs/language/learn-ql/locations.rst index df210819ef2..a06f428bef8 100644 --- a/docs/language/learn-ql/locations.rst +++ b/docs/language/learn-ql/locations.rst @@ -1,10 +1,13 @@ -Locations and strings for QL entities +Providing locations in CodeQL queries ===================================== .. Not sure how much of this topic needs to change, and what the title should be -Providing locations -------------------- +CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. + + +About locations +--------------- When displaying information to the user, LGTM needs to be able to extract location information from the results of a query. In order to do this, all QL classes which can provide location information should do this by using one of the following mechanisms: diff --git a/docs/language/learn-ql/python/control-flow-graph.rst b/docs/language/learn-ql/python/control-flow-graph.rst deleted file mode 100644 index 099c252784b..00000000000 --- a/docs/language/learn-ql/python/control-flow-graph.rst +++ /dev/null @@ -1,9 +0,0 @@ -Python control flow graph -========================= - -:doc:`Back to tutorial: control flow analysis ` - -|Python control flow graph| - -.. |Python control flow graph| image:: ../../images/python-flow-graph.png - diff --git a/docs/language/learn-ql/python/control-flow.rst b/docs/language/learn-ql/python/control-flow.rst index fc41f59c933..9291f4dc907 100644 --- a/docs/language/learn-ql/python/control-flow.rst +++ b/docs/language/learn-ql/python/control-flow.rst @@ -1,7 +1,12 @@ -Tutorial: Control flow analysis -=============================== +Analyzing control flow in Python +================================ -To analyze the `Control-flow graph `__ of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. +You can write CodeQL queries to explore the control-flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. + +About analyzing control flow +-------------------------------------- + +To analyze the control-flow graph of a ``Scope`` we can use the two CodeQL classes ``ControlFlowNode`` and ``BasicBlock``. These classes allow you to ask such questions as "can you reach point A from point B?" or "Is it possible to reach point B *without* going through point A?". To report results we use the class ``AstNode``, which represents a syntactic element and corresponds to the source code - allowing the results of the query to be more easily understood. For more information, see `Control-flow graph `__ on Wikipedia. The ``ControlFlowNode`` class ----------------------------- @@ -19,11 +24,18 @@ To show why this complex relation is required consider the following Python code finally: close_resource() -There are many paths through the above code. There are three different paths through the call to ``close_resource();`` one normal path, one path that breaks out of the loop, and one path where an exception is raised by ``might_raise()``. (An annotated flow graph can be seen :doc:`here `.) +There are many paths through the above code. There are three different paths through the call to ``close_resource();`` one normal path, one path that breaks out of the loop, and one path where an exception is raised by ``might_raise()``. + +An annotated flow graph: + +|Python control flow graph| + +.. |Python control flow graph| image:: ../../images/python-flow-graph.png The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find unreachable code. There is one ``ControlFlowNode`` per path through any ``AstNode`` and any ``AstNode`` that is unreachable has no paths flowing through it. Therefore, any ``AstNode`` without a corresponding ``ControlFlowNode`` is unreachable. -**Unreachable AST nodes** +Example finding unreachable AST nodes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql @@ -33,9 +45,10 @@ The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find u where not exists(node.getAFlowNode()) select node -➤ `See this in the query console `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements: +➤ `See this in the query console on LGTM.com `__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements. -**Unreachable statements** +Example finding unreachable statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql @@ -45,15 +58,15 @@ The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find u where not exists(s.getAFlowNode()) select s -➤ `See this in the query console `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard query: `Unreachable code `__. +➤ `See this in the query console on LGTM.com `__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard "Unreachable code" query. For more information, see `Unreachable code `__ on LGTM.com. The ``BasicBlock`` class ------------------------ -The ``BasicBlock`` class represents a `basic block `__ of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as what can reach what and what `dominates `__ what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. +The ``BasicBlock`` class represents a basic block of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as, what can reach what, and what dominates what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory. For more information, see `Basic block `__ and `Dominator `__ on Wikipedia. -Example: Finding mutually exclusive basic blocks -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding mutually exclusive basic blocks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Suppose we have the following Python code: @@ -84,7 +97,8 @@ However, by that definition, two basic blocks are mutually exclusive if they are Combining these conditions we get: -**Mutually exclusive blocks within the same function** +Example finding mutually exclusive blocks within the same function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: ql @@ -98,10 +112,11 @@ Combining these conditions we get: ) select b1, b2 -➤ `See this in the query console `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis which is covered in the next tutorial. +➤ `See this in the query console on LGTM.com `__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see :doc:`Analyzing data flow and tracking tainted data in Python `. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the tutorial topic :doc:`Taint tracking and data flow analysis in Python `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/functions.rst b/docs/language/learn-ql/python/functions.rst index c3c8a5e6eac..20e47267825 100644 --- a/docs/language/learn-ql/python/functions.rst +++ b/docs/language/learn-ql/python/functions.rst @@ -1,7 +1,9 @@ -Tutorial: Functions +Functions in Python =================== -This example uses the standard CodeQL class ``Function`` (see :doc:`Introducing the Python libraries `). +You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. + +These examples use the standard CodeQL class `Function `__. For more information, see ":doc:`Introducing the Python libraries `." Finding all functions called "get..." ------------------------------------- @@ -24,7 +26,7 @@ Using the member predicate ``Function.getName()``, we can list all of the getter where f.getName().matches("get%") select f, "This is a function called get..." -➤ `See this in the query console `__. This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in. +➤ `See this in the query console on LGTM.com `__. This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in. Finding all methods called "get..." ----------------------------------- @@ -39,7 +41,7 @@ You can modify the query above to return more interesting results. As we are onl where f.getName().matches("get%") and f.isMethod() select f, "This is a method called get..." -➤ `See this in the query console `__. This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in. +➤ `See this in the query console on LGTM.com `__. This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in. Finding one line methods called "get..." ---------------------------------------- @@ -55,7 +57,7 @@ We can modify the query further to include only methods whose body consists of a and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -➤ `See this in the query console `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in :doc:`Tutorial: Statements and expressions `. +➤ `See this in the query console on LGTM.com `__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python `." Finding a call to a specific function ------------------------------------- @@ -70,14 +72,18 @@ This query uses ``Call`` and ``Name`` to find calls to the function ``eval`` - w where call.getFunc() = name and name.getId() = "eval" select call, "call to 'eval'." -➤ `See this in the query console `__. Some of the demo projects on LGTM.com use this function. +➤ `See this in the query console on LGTM.com `__. Some of the demo projects on LGTM.com use this function. The ``Call`` class represents calls in Python. The ``Call.getFunc()`` predicate gets the expression being called. ``Name.getId()`` gets the identifier (as a string) of the ``Name`` expression. Due to the dynamic nature of Python, this query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not. In a later tutorial we will see how to use the type-inference library to find calls to the built-in function ``eval`` regardless of name of the variable called. -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Statements and expressions `, :doc:`Control flow `, and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Expressions and statements in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/introduce-libraries-python.rst b/docs/language/learn-ql/python/introduce-libraries-python.rst index 54276aedd8e..d124277d0b5 100644 --- a/docs/language/learn-ql/python/introduce-libraries-python.rst +++ b/docs/language/learn-ql/python/introduce-libraries-python.rst @@ -1,17 +1,19 @@ -Introducing the CodeQL libraries for Python -=========================================== +CodeQL library for Python +========================= -There is an extensive library for analyzing CodeQL databases extracted from Python projects. The classes in this library present the data from a database in an object-oriented form and provide abstractions and predicates to help you with common analysis tasks. The library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: +When you need to analyze a Python program, you can make use of the large collection of classes in the CodeQL library for Python. + +About the CodeQL library for Python +----------------------------------- + +The CodeQL library for each programming language uses classes with abstractions and predicates to present data in an object-oriented form. + +Each CodeQL library is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with: .. code-block:: ql import python -The rest of this tutorial summarizes the contents of the standard libraries for Python. We recommend that you read this and then work through the practical examples in the tutorials shown at the end of the page. - -Overview of the library ------------------------ - The CodeQL library for Python incorporates a large number of classes. Each class corresponds either to one kind of entity in Python source code or to an entity that can be derived from the source code using static analysis. These classes can be divided into four categories: - **Syntactic** - classes that represent entities in the Python source code. @@ -20,16 +22,14 @@ The CodeQL library for Python incorporates a large number of classes. Each class - **Taint tracking** - classes that represent the source, sinks and kinds of taint used to implement taint-tracking queries. Syntactic classes -~~~~~~~~~~~~~~~~~ +----------------- -This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an `Abstract syntax tree `__ (AST). The root of each AST is a ``Module``. - -`Symbolic information `__ is attached to the AST in the form of variables (represented by the class ``Variable``). +This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Abstract syntax tree `__ and `Symbolic information `__ on Wikipedia. Scope ^^^^^ -A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes `Module `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. - ``Scope`` @@ -47,7 +47,7 @@ All scopes are basically a list of statements, although ``Scope`` classes have a where f.getScope() instanceof Function select f -➤ `See this in the query console `__. Many projects have nested functions. +➤ `See this in the query console on LGTM.com `__. Many projects have nested functions. Statement ^^^^^^^^^ @@ -89,7 +89,7 @@ As an example, to find expressions of the form ``a+2`` where the left is a simpl where bin.getLeft() instanceof Name and bin.getRight() instanceof Num select bin -➤ `See this in the query console `__. Many projects include examples of this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects include examples of this pattern. Variable ^^^^^^^^ @@ -120,7 +120,7 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c from Try t select t.getFinalbody() -➤ `See this in the query console `__. Many projects include examples of this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects include examples of this pattern. 2. Finding ``except`` blocks that do nothing '''''''''''''''''''''''''''''''''''''''''''' @@ -151,7 +151,7 @@ Both forms are equivalent. Using the positive expression, the whole query looks where forall(Stmt s | s = ex.getAStmt() | s instanceof Pass) select ex -➤ `See this in the query console `__. Many projects include pass-only ``except`` blocks. +➤ `See this in the query console on LGTM.com `__. Many projects include pass-only ``except`` blocks. Summary ^^^^^^^ @@ -237,11 +237,14 @@ Other - ``Comment`` – A comment Control flow classes -~~~~~~~~~~~~~~~~~~~~ +-------------------- -This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into `basic blocks `__. +This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into basic blocks. For more information, see `Basic block `__ on Wikipedia. -As an example, we might want to find the longest sequence of code without any branches. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``. +Example +^^^^^^^ + +If we want to find the longest sequence of code without any branches, we need to consider control flow. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``. First of all we introduce a simple predicate ``bb_length()`` which relates ``BasicBlock``\ s to their length. @@ -269,7 +272,7 @@ Using this predicate we can select the longest ``BasicBlock`` by selecting the ` where bb_length(b) = max(bb_length(_)) select b -➤ `See this in the query console `__. When we ran it on the LGTM.com demo projects, the *openstack/nova* and *ytdl-org/youtube-dl* projects both contained source code results for this query. +➤ `See this in the query console on LGTM.com `__. When we ran it on the LGTM.com demo projects, the *openstack/nova* and *ytdl-org/youtube-dl* projects both contained source code results for this query. .. pull-quote:: @@ -289,7 +292,12 @@ The classes in the control-flow part of the library are: Type-inference classes ---------------------- -The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime. For example, which ``ClassValue``\ s are iterable can be determined using the query: +The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime. + +Example +^^^^^^^ + +For example, which ``ClassValue``\ s are iterable can be determined using the query: **Find iterable "ClassValue"s** @@ -301,10 +309,10 @@ The CodeQL library for Python also supplies some classes for accessing the infer where cls.hasAttribute("__iter__") select cls -➤ `See this in the query console `__ This query returns a list of classes for the projects analyzed. If you want to include the results for `builtin classes `__, which do not have any Python source code, show the non-source results. +➤ `See this in the query console on LGTM.com `__ This query returns a list of classes for the projects analyzed. If you want to include the results for ``builtin`` classes, which do not have any Python source code, show the non-source results. For more information, see `builtin classes `__ in the Python documentation. Summary -~~~~~~~ +^^^^^^^ - `Value `__ @@ -312,7 +320,7 @@ Summary - ``CallableValue`` - ``ModuleValue`` -These classes are explained in more detail in :doc:`Tutorial: Points-to analysis and type inference `. +For more information about these classes, see ":doc:`Pointer analysis and type inference in Python `." Taint-tracking classes ---------------------- @@ -321,16 +329,21 @@ The CodeQL library for Python also supplies classes to specify taint-tracking an Summary -~~~~~~~ +^^^^^^^ - `TaintKind `__ - `Configuration `__ -These classes are explained in more detail in :doc:`Tutorial: Taint tracking and data flow analysis in Python `. +For more information about these classes, see ":doc:`Analyzing data flow and tracking tainted data in Python `." -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Functions `, :doc:`Statements and expressions `, :doc:`Control flow `, :doc:`Points-to analysis and type inference `, and :doc:`Taint tracking and data flow analysis in Python `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Functions in Python `" +- ":doc:`Expressions and statements in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 7ae9368d02c..8fbde0d9b35 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -1,7 +1,7 @@ -Tutorial: Points-to analysis and type inference -=============================================== +Pointer analysis and type inference in Python +============================================= -This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference. +At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime by using type-inference classes from the standard CodeQL library. The ``Value`` class -------------------- @@ -9,7 +9,7 @@ The ``Value`` class The ``Value`` class and its subclasses ``FunctionValue``, ``ClassValue``, and ``ModuleValue`` represent the values an expression may hold at runtime. Summary -~~~~~~~ +^^^^^^^ Class hierarchy for ``Value``: @@ -22,9 +22,7 @@ Class hierarchy for ``Value``: Points-to analysis and type inference ------------------------------------- -Points-to analysis, sometimes known as `pointer analysis `__, allows us to determine which objects an expression may "point to" at runtime. - -`Type inference `__ allows us to infer what the types (classes) of an expression may be at runtime. +Points-to analysis, sometimes known as pointer analysis, allows us to determine which objects an expression may "point to" at runtime. Type inference allows us to infer what the types (classes) of an expression may be at runtime. For more information, see `Pointer analysis `__ and `Type inference `__ on Wikipedia. The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flow node may "point to" at runtime. @@ -76,7 +74,7 @@ First we can write a query to find ordered pairs of ``except`` blocks for a ``tr ) select t, ex1, ex2 -➤ `See this in the query console `__. Many projects contain ordered ``except`` blocks in a ``try`` statement. +➤ `See this in the query console on LGTM.com `__. Many projects contain ordered ``except`` blocks in a ``try`` statement. Here ``ex1`` and ``ex2`` are both ``except`` handlers in the ``try`` statement ``t``. By using the indices ``i`` and ``j`` we can also ensure that ``ex1`` precedes ``ex2``. @@ -123,7 +121,7 @@ Combining the parts of the query we get this: ) select t, ex1, ex2 -➤ `See this in the query console `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard query: `Unreachable 'except' block `__. +➤ `See this in the query console on LGTM.com `__. This query finds only one result in the demo projects on LGTM.com (`youtube-dl `__). The result is also highlighted by the standard "Unreachable 'except' block" query. For more information, see `Unreachable 'except' block `__ on LGTM.com. .. pull-quote:: @@ -158,7 +156,7 @@ Then we need to determine if the object ``iter`` is iterable. We can test ``Clas not exists(cls.lookup("__iter__")) select loop, cls -➤ `See this in the query console `__. Many projects use a non-iterable as a loop iterator. +➤ `See this in the query console on LGTM.com `__. Many projects use a non-iterable as a loop iterator. Many of the results shown will have ``cls`` as ``NoneType``. It is more informative to show where these ``None`` values may come from. To do this we use the final field of ``pointsTo``, as follows: @@ -174,7 +172,7 @@ Many of the results shown will have ``cls`` as ``NoneType``. It is more informat not cls.hasAttribute("__iter__") select loop, cls, origin -➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. +➤ `See this in the query console on LGTM.com `__. This reports the same results, but with a third column showing the source of the ``None`` values. Finding calls using call-graph analysis ---------------------------------------------------- @@ -183,7 +181,7 @@ The ``Value`` class has a method ``getACall()`` which allows us to find calls to If we wish to restrict the callables to actual functions we can use the ``FunctionValue`` class, which is a subclass of ``Value`` and corresponds to function objects in Python, in much the same way as the ``ClassValue`` class corresponds to class objects in Python. -Returning to an example from :doc:`Tutorial: Functions `, we wish to find calls to the ``eval`` function. +Returning to an example from ":doc:`Functions in Python `," we wish to find calls to the ``eval`` function. The original query looked this: @@ -195,7 +193,7 @@ The original query looked this: where call.getFunc() = name and name.getId() = "eval" select call, "call to 'eval'." -➤ `See this in the query console `__. Some of the demo projects on LGTM.com have calls that match this pattern. +➤ `See this in the query console on LGTM.com `__. Some of the demo projects on LGTM.com have calls that match this pattern. There are two problems with this query: @@ -223,10 +221,12 @@ Then we can use ``Value.getACall()`` to identify calls to the ``eval`` function, call = eval.getACall() select call, "call to 'eval'." -➤ `See this in the query console `__. This accurately identifies calls to the builtin ``eval`` function even when they are referred to using an alternative name. Any false positive results with calls to other ``eval`` functions, reported by the original query, have been eliminated. +➤ `See this in the query console on LGTM.com `__. This accurately identifies calls to the builtin ``eval`` function even when they are referred to using an alternative name. Any false positive results with calls to other ``eval`` functions, reported by the original query, have been eliminated. -What next? ----------- +Further reading +--------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. -- Read a description of the CodeQL database in :doc:`What's in a CodeQL database? <../database>` +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/ql-for-python.rst b/docs/language/learn-ql/python/ql-for-python.rst index 680c0c374b5..c9aa0a241e6 100644 --- a/docs/language/learn-ql/python/ql-for-python.rst +++ b/docs/language/learn-ql/python/ql-for-python.rst @@ -1,37 +1,35 @@ CodeQL for Python ================= +Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Python codebases. + .. toctree:: - :glob: :hidden: introduce-libraries-python functions statements-expressions - control-flow - control-flow-graph - taint-tracking pointsto-type-infer + control-flow + taint-tracking -The following tutorials and worked examples are designed to help you learn how to write effective and efficient queries for Python projects. You should work through these topics in the order displayed. +- `Basic Python query `__ : Learn to write and run a simple CodeQL query using LGTM. -- `Basic Python query `__ describes how to write and run queries using LGTM. +- :doc:`CodeQL library for Python `: When you need to analyze a Python program, you can make use of the large collection of classes in the CodeQL library for Python. -- :doc:`Introducing the CodeQL libraries for Python ` introduces the standard libraries used to write queries for Python code. +- :doc:`Functions in Python `: You can use syntactic classes from the standard CodeQL library to find Python functions and identify calls to them. -- :doc:`Tutorial: Functions ` demonstrates how to write queries using the standard CodeQL library classes for Python functions. +- :doc:`Expressions and statements in Python `: You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a codebase. -- :doc:`Tutorial: Statements and expressions ` demonstrates how to write queries using the standard CodeQL library classes for Python statements and expressions. +- :doc:`Analyzing control flow in Python `: You can write CodeQL queries to explore the control-flow graph of a Python program, for example, to discover unreachable code or mutually exclusive blocks of code. -- :doc:`Tutorial: Control flow ` demonstrates how to write queries using the standard CodeQL library classes for Python control flow. +- :doc:`Pointer analysis and type inference in Python `: At runtime, each Python expression has a value with an associated type. You can learn how an expression behaves at runtime by using type-inference classes from the standard CodeQL library. -- :doc:`Tutorial: Points-to analysis and type inference ` demonstrates how to write queries using the standard CodeQL library classes for Python type inference. +- :doc:`Analyzing data flow and tracking tainted data in Python `: You can use CodeQL to track the flow of data through a Python program. Tracking user-controlled, or tainted, data is a key technique for security researchers. -- :doc:`Taint tracking and data flow analysis in Python ` demonstrates how to write queries using the standard taint tracking and data flow libraries for Python. - -Other resources +Further reading --------------- -- For examples of how to query common Python elements, see the `Python cookbook `__. -- For the queries used in LGTM, display a `Python query `__ and click **Open in query console** to see the code used to find alerts. -- For more information about the library for Python see the `CodeQL library for Python `__. +- For examples of how to query common Python elements, see the `JavaScript cookbook `__. +- For the queries used in LGTM, display a `Python query `__ and click **Open in query console** to see the code used to find alerts. +- For more information about the library for JavaScript see the `CodeQL library for Python `__. diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index d3b4e68af6c..9e817d5c5c6 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -1,6 +1,8 @@ -Tutorial: Statements and expressions +Expressions and statements in Python ==================================== +You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a code base. + Statements ---------- @@ -37,13 +39,11 @@ Here is the full class hierarchy: - ``While`` – A ``while`` statement - ``With`` – A ``with`` statement -Example: Finding redundant 'global' statements -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding redundant 'global' statements +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The ``global`` statement in Python declares a variable with a global (module-level) scope, when it would otherwise be local. Using the ``global`` statement outside a class or function is redundant as the variable is already global. -**Finding redundant global statements** - .. code-block:: ql import python @@ -52,17 +52,15 @@ The ``global`` statement in Python declares a variable with a global (module-lev where g.getScope() instanceof Module select g -➤ `See this in the query console `__. None of the demo projects on LGTM.com has a global statement that matches this pattern. +➤ `See this in the query console on LGTM.com `__. None of the demo projects on LGTM.com has a global statement that matches this pattern. The line: ``g.getScope() instanceof Module`` ensures that the ``Scope`` of ``Global g`` is a ``Module``, rather than a class or function. -Example: Finding 'if' statements with redundant branches --------------------------------------------------------- +Example finding 'if' statements with redundant branches +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ An ``if`` statement where one branch is composed of just ``pass`` statements could be simplified by negating the condition and dropping the ``else`` clause. -**An 'if' statement that could be simplified** - .. code-block:: python if cond(): @@ -70,9 +68,7 @@ An ``if`` statement where one branch is composed of just ``pass`` statements cou else: do_something -To find statements like this we can run the following query: - -**Find 'if' statements with empty branches** +To find statements like this that could be simplified we can write a query. .. code-block:: ql @@ -83,7 +79,7 @@ To find statements like this we can run the following query: and forall(Stmt p | p = l.getAnItem() | p instanceof Pass) select i -➤ `See this in the query console `__. Many projects have some ``if`` statements that match this pattern. +➤ `See this in the query console on LGTM.com `__. Many projects have some ``if`` statements that match this pattern. The line: ``(l = i.getBody() or l = i.getOrelse())`` restricts the ``StmtList l`` to branches of the ``if`` statement. @@ -131,8 +127,8 @@ Each kind of Python expression has its own class. Here is the full class hierarc - ``Yield`` – A ``yield`` expression - ``YieldFrom`` – A ``yield from`` expression (Python 3.3+) -Example: Finding comparisons to integer or string literals using 'is' -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding comparisons to integer or string literals using 'is' +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Python implementations commonly cache small integers and single character strings, which means that comparisons such as the following often work correctly, but this is not guaranteed and we might want to check for them. @@ -141,9 +137,7 @@ Python implementations commonly cache small integers and single character string x is 10 x is "A" -We can check for these as follows: - -**Find comparisons to integer or string literals using** ``is`` +We can check for these using a query. .. code-block:: ql @@ -154,7 +148,7 @@ We can check for these as follows: and cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal select cmp -➤ `See this in the query console `__. Two of the demo projects on LGTM.com use this pattern: *saltstack/salt* and *openstack/nova*. +➤ `See this in the query console on LGTM.com `__. Two of the demo projects on LGTM.com use this pattern: *saltstack/salt* and *openstack/nova*. The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal. @@ -164,15 +158,11 @@ The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` che We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``). -Example: Duplicates in dictionary literals -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding duplicates in dictionary literals +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ If there are duplicate keys in a Python dictionary, then the second key will overwrite the first, which is almost certainly a mistake. We can find these duplicates with CodeQL, but the query is more complex than previous examples and will require us to write a ``predicate`` as a helper. -Here is the query: - -**Find duplicate dictionary keys** - .. code-block:: ql import python @@ -188,7 +178,7 @@ Here is the query: and k1 != k2 and same_key(k1, k2) select k1, "Duplicate key in dict literal" -➤ `See this in the query console `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard `Duplicate key in dict literal `__ query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. +➤ `See this in the query console on LGTM.com `__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. For more information, see `Duplicate key in dict literal `__ on LGTM.com. The supporting predicate ``same_key`` checks that the keys have the same identifier. Separating this part of the logic into a supporting predicate, instead of directly including it in the query, makes it easier to understand the query as a whole. The casts defined in the predicate restrict the expression to the type specified and allow predicates to be called on the type that is cast-to. For example: @@ -204,12 +194,10 @@ is equivalent to The short version is usually used as this is easier to read. -Example: Finding Java-style getters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example finding Java-style getters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Returning to the example from :doc:`Tutorial: Functions `, the query identified all methods with a single line of code and a name starting with ``get``: - -**Basic: Find Java-style getters** +Returning to the example from ":doc:`Functions in Python `," the query identified all methods with a single line of code and a name starting with ``get``. .. code-block:: ql @@ -220,9 +208,7 @@ Returning to the example from :doc:`Tutorial: Functions `, the query and count(f.getAStmt()) = 1 select f, "This function is (probably) a getter." -This basic query can be improved by checking that the one line of code is of the form ``return self.attr`` - -**Improved: Find Java-style getters** +This basic query can be improved by checking that the one line of code is a Java-style getter of the form ``return self.attr``. .. code-block:: ql @@ -234,23 +220,19 @@ This basic query can be improved by checking that the one line of code is of the and attr.getObject() = self and self.getId() = "self" select f, "This function is a Java-style getter." -➤ `See this in the query console `__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters. - -In this query, the condition: +➤ `See this in the query console on LGTM.com `__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters. .. code-block:: ql ret = f.getStmt(0) and ret.getValue() = attr -checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``. - -The condition: +This condition checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``. .. code-block:: ql attr.getObject() = self and self.getId() = "self" -checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``. +This condition checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``. Class and function definitions ------------------------------ @@ -271,8 +253,12 @@ Here is the relevant part of the class hierarchy: - ``Class`` - ``Function`` -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Control flow ` and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Functions in Python `" +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/python/taint-tracking.rst b/docs/language/learn-ql/python/taint-tracking.rst index 2ea24369bf4..bfdae7aa4eb 100644 --- a/docs/language/learn-ql/python/taint-tracking.rst +++ b/docs/language/learn-ql/python/taint-tracking.rst @@ -1,8 +1,10 @@ -Taint tracking and data flow analysis in Python -=============================================== +Analyzing data flow and tracking tainted data in Python +======================================================= -Overview --------- +You can use CodeQL to track the flow of data through a Python program. Tracking user-controlled, or tainted, data is a key technique for security researchers. + +About data flow and taint tracking +---------------------------------- Taint tracking is used to analyze how potentially insecure, or 'tainted' data flows throughout a program at runtime. You can use taint tracking to find out whether user-controlled input can be used in a malicious way, @@ -14,12 +16,12 @@ For example, in the assignment ``dir = path + "/"``, if ``path`` is tainted then even though there is no data flow from ``path`` to ``path + "/"``. Separate CodeQL libraries have been written to handle 'normal' data flow and taint tracking in :doc:`C/C++ <../cpp/dataflow>`, :doc:`C# <../csharp/dataflow>`, :doc:`Java <../java/dataflow>`, and :doc:`JavaScript <../javascript/dataflow>`. You can access the appropriate classes and predicates that reason about these different modes of data flow by importing the appropriate library in your query. -In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve value and those that don't by defining additional data flow properties. +In Python analysis, we can use the same taint tracking library to model both 'normal' data flow and taint flow, but we are still able make the distinction between steps that preserve values and those that don't by defining additional data flow properties. -For further information on data flow and taint tracking with CodeQL, see :doc:`Introduction to data flow <../intro-to-data-flow>`. +For further information on data flow and taint tracking with CodeQL, see ":doc:`Introduction to data flow <../intro-to-data-flow>`." -Fundamentals of taint tracking and data flow analysis -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Fundamentals of taint tracking using data flow analysis +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The taint tracking library is in the `TaintTracking `__ module. Any taint tracking or data flow analysis query has three explicit components, one of which is optional, and an implicit component. @@ -39,7 +41,7 @@ The kind of taint determines which non-value-preserving steps are possible, in a In the above example ``dir = path + "/"``, taint flows from ``path`` to ``dir`` if the taint represents a string, but not if the taint is ``None``. Limitations -~~~~~~~~~~~ +^^^^^^^^^^^ Although taint tracking is a powerful technique, it is worth noting that it depends on the underlying data flow graphs. Creating a data flow graph that is both accurate and covers a large enough part of a program is a challenge, @@ -79,6 +81,9 @@ A simple taint tracking query has the basic form: where config.hasFlow(src, sink) select sink, "Alert message, including reference to $@.", src, "string describing the source" +Example +^^^^^^^ + As a contrived example, here is a query that looks for flow from a HTTP request to a function called ``"unsafe"``. The sources are predefined and accessed by importing library ``semmle.python.web.HttpRequest``. The sink is defined by using a custom ``TaintTracking::Sink`` class. @@ -126,8 +131,8 @@ The sink is defined by using a custom ``TaintTracking::Sink`` class. -Implementing path queries -~~~~~~~~~~~~~~~~~~~~~~~~~ +Converting a taint-tracking query to a path query +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Although the taint tracking query above tells which sources flow to which sinks, it doesn't tell us how. For that we need a path query. @@ -202,8 +207,8 @@ Thus, our example query becomes: -Custom taint kinds and flows ----------------------------- +Tracking custom taint kinds and flows +------------------------------------- In the above examples, we have assumed the existence of a suitable ``TaintKind``, but sometimes it is necessary to model the flow of other objects, such as database connections, or ``None``. @@ -226,8 +231,8 @@ The ``TaintKind`` itself is just a string (a QL string, not a CodeQL entity repr which provides methods to extend flow and allow the kind of taint to change along the path. The ``TaintKind`` class has many predicates allowing flow to be modified. This simplest ``TaintKind`` does not override any predicates, meaning that it only flows as opaque data. -An example of this is the `Hard-coded credentials query `_, -which defines the simplest possible taint kind class, ``HardcodedValue``, and custom source and sink classes. +An example of this is the "Hard-coded credentials" query, +which defines the simplest possible taint kind class, ``HardcodedValue``, and custom source and sink classes. For more information, see `Hard-coded credentials `_ on LGTM.com. .. code-block:: ql @@ -251,8 +256,11 @@ which defines the simplest possible taint kind class, ``HardcodedValue``, and cu } } -What next? ----------- +Further reading +--------------- -- Experiment with the worked examples in the following tutorial topics: :doc:`Control flow ` and :doc:`Points-to analysis and type inference `. -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- ":doc:`Pointer analysis and type inference in Python `" +- ":doc:`Analyzing control flow in Python `" +- ":doc:`Analyzing data flow and tracking tainted data in Python `" + +.. include:: ../../reusables/python-other-resources.rst diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index 55c3d33f705..5b014ca72fc 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -32,7 +32,7 @@ We recommend that you download `CodeQL for Visual Studio Code `__–an example demonstrating how to develop a data flow query. - `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL. -More resources -~~~~~~~~~~~~~~ +Further reading +~~~~~~~~~~~~~~~ - If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. -- To find more detailed information about how to write queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. -- To see examples of CodeQL queries that have been used to find security vulnerabilities and bugs in open-source software projects, visit the `GitHub Security Lab website `__ and the associated `repository `__. \ No newline at end of file +- To see examples of CodeQL queries that have been used to find security vulnerabilities and bugs in open source software projects, visit the `GitHub Security Lab website `__ and the associated `repository `__. \ No newline at end of file diff --git a/docs/language/learn-ql/writing-queries/debugging-queries.rst b/docs/language/learn-ql/writing-queries/debugging-queries.rst index b0b03321354..9eee078d18c 100644 --- a/docs/language/learn-ql/writing-queries/debugging-queries.rst +++ b/docs/language/learn-ql/writing-queries/debugging-queries.rst @@ -1,12 +1,17 @@ -Query writing: common performance issues -======================================== +Troubleshooting query performance +================================= + +Improve the performance of your CodeQL queries by following a few simple guidelines. + +About query performance +----------------------- This topic offers some simple tips on how to avoid common problems that can affect the performance of your queries. Before reading the tips below, it is worth reiterating a few important points about CodeQL and the QL language: - CodeQL `predicates `__ and `classes `__ are evaluated to database `tables `__. Large predicates generate large tables with many rows, and are therefore expensive to compute. -- The QL language is implemented using standard database operations and `relational algebra `__ (such as join, projection, and union). For further information about query languages and databases, see :doc:`About QL <../about-ql>`. -- Queries are evaluated *bottom-up*, which means that a predicate is not evaluated until *all* of the predicates that it depends on are evaluated. For more information on query evaluation, see `Evaluation of QL programs `__ in the QL handbook. +- The QL language is implemented using standard database operations and `relational algebra `__ (such as join, projection, and union). For further information about query languages and databases, see `About the QL language `__. +- Queries are evaluated *bottom-up*, which means that a predicate is not evaluated until *all* of the predicates that it depends on are evaluated. For more information on query evaluation, see `Evaluation of QL programs `__. Performance tips ---------------- @@ -19,9 +24,7 @@ Eliminate cartesian products The performance of a predicate can often be judged by considering roughly how many results it has. One way of creating badly performing predicates is by using two variables without relating them in any way, or only relating them using a negation. This leads to computing the `Cartesian product `__ between the sets of possible values for each variable, potentially generating a huge table of results. - This can occur if you don't specify restrictions on your variables. - For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``:: predicate mayAccess(Method m, Field f) { @@ -148,4 +151,4 @@ Now the structure we want is clearer. We've separated out the easy part into its Further information ------------------- -- Find out more about QL in the `QL language handbook `__ and `QL language specification `__. +- Find out more about QL in the `QL language reference `__. diff --git a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst index 76b419d4966..fc17a2e8d36 100644 --- a/docs/language/learn-ql/writing-queries/introduction-to-queries.rst +++ b/docs/language/learn-ql/writing-queries/introduction-to-queries.rst @@ -1,10 +1,12 @@ -Introduction to query files -########################### +About CodeQL queries +#################### + +CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. Overview ******** -Queries are programs written with CodeQL. They are designed to highlight issues related to the security, correctness, maintainability, and readability of a code base. You can also write custom queries to find specific issues relevant to your own project. Three important types of query are: +CodeQL includes queries to find the most relevant and interesting problems for each supported language. You can also write custom queries to find specific issues relevant to your own project. The important types of query are: - **Alert queries**: queries that highlight issues in specific locations in your code. - **Path queries**: queries that describe the flow of information between a source and a sink in your code. @@ -21,9 +23,8 @@ You can add custom queries to `custom query packs `__ and in the `Results view `__ in VS Code. -This topic is a basic introduction to structuring query files. You can find further information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language handbook `__ and the `QL language specification `__. -For information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. - +This topic is a basic introduction to query files. You can find more information on writing queries for specific programming languages `here `__, and detailed technical information about QL in the `QL language reference `__. +For more information on how to format your code when contributing queries to the GitHub repository, see the `CodeQL style guide `__. Basic query structure ********************* @@ -44,7 +45,7 @@ Basic query structure where /* ... logical formula ... */ select /* ... expressions ... */ -The following sections describe the information that is typically included in a query file for alerts and metrics. Path queries are discussed in more detail in :doc:`Constructing path queries `. +The following sections describe the information that is typically included in a query file for alerts and metrics. Path queries are discussed in more detail in :doc:`Creating path queries `. Query metadata ============== @@ -54,7 +55,7 @@ Query metadata is used to identify your custom queries when they are added to th - If you are contributing a query to the GitHub repository, please read the `query metadata style guide `__. - If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis `__. - If you are analyzing a database using the `CodeQL CLI `__, your query metadata must contain ``@kind``. -- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. See `Using the query console `__ and `Using the extension `__ for further information. +- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. For more information, see `Using the query console `__ on LGTM.com and `Using the extension `__ in the CodeQL for VS Code help. .. pull-quote:: @@ -83,21 +84,20 @@ When writing your own alert queries, you would typically import the standard lib - JavaScript/TypeScript: ``javascript`` - Python: ``python`` -There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. See :doc:`Constructing path queries ` for further information. +There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. For more information, see :doc:`Creating path queries `. You can explore the contents of all the standard libraries in the `CodeQL library reference documentation `__ or in the `GitHub repository `__. - Optional CodeQL classes and predicates -------------------------------------- -You can customize your analysis by defining your own predicates and classes in the query. See `Defining a predicate `__ and `Defining a class `__ for further details. +You can customize your analysis by defining your own predicates and classes in the query. For further information, see `Defining a predicate `__ and `Defining a class `__. From clause =========== The ``from`` clause declares the variables that are used in the query. Each declaration must be of the form `` ``. -For more information on the available `types `__, and to learn how to define your own types using `classes `__, see the `QL language handbook `__. +For more information on the available `types `__, and to learn how to define your own types using `classes `__, see the `QL language reference `__. Where clause ============ @@ -117,9 +117,9 @@ Select clauses for alert queries (``@kind problem``) consist of two 'columns', w - ``element``: a code element that is identified by the query, which defines where the alert is displayed. - ``string``: a message, which can also include links and placeholders, explaining why the alert was generated. -The alert message defined in the final column of the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining 'select' statements `. +You can modify the alert message defined in the final column of the ``select`` statement to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining the results of a query `. -Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. See :doc:`Constructing path queries ` for further information. +Select clauses for path queries (``@kind path-problem``) are crafted to display both an alert and the source and sink of an associated path graph. For more information, see :doc:`Creating path queries `. Select clauses for metric queries (``@kind metric``) consist of two 'columns', with the following structure:: @@ -128,16 +128,34 @@ Select clauses for metric queries (``@kind metric``) consist of two 'columns', w - ``element``: a code element that is identified by the query, which defines where the alert is displayed. - ``metric``: the result of the metric that the query computes. +Viewing the standard CodeQL queries +*********************************** + +One of the easiest ways to get started writing your own queries is to modify an existing query. To view the standard CodeQL queries, or to try out other examples, visit the `CodeQL `__ and `CodeQL for Go `__ repositories on GitHub. + +You can also find examples of queries developed to find security vulnerabilities and bugs in open source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. + +Contributing queries +******************** + +Contributions to the standard queries and libraries are very welcome. For more information, see our `contributing guidelines `__. +If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with the CodeQL CLI, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: + +- :doc:`Metadata for CodeQL queries ` +- `Query metadata style guide on GitHub `__ + +Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help files `. + Query help files **************** -When you write a custom query, we also recommend that you write a query help file to explain the purpose of the query to other users. For more information, see the `Query help style guide `__ on GitHub, and the :doc:`Query help reference `. +When you write a custom query, we also recommend that you write a query help file to explain the purpose of the query to other users. For more information, see the `Query help style guide `__ on GitHub, and the :doc:`Query help files `. What next? ========== - See the queries used in real-life variant analysis on the `GitHub Security Lab website `__. -- To learn more about writing path queries, see :doc:`Constructing path queries `. +- To learn more about writing path queries, see :doc:`Creating path queries `. - Take a look at the `built-in queries `__ to see examples of the queries included in CodeQL. - Explore the `query cookbooks `__ to see how to access the basic language elements contained in the CodeQL libraries. - For a full list of resources to help you learn CodeQL, including beginner tutorials and language-specific examples, visit `Learning CodeQL `__. diff --git a/docs/language/learn-ql/writing-queries/path-queries.rst b/docs/language/learn-ql/writing-queries/path-queries.rst index 7b3d52515c3..4bdd328dca8 100644 --- a/docs/language/learn-ql/writing-queries/path-queries.rst +++ b/docs/language/learn-ql/writing-queries/path-queries.rst @@ -1,5 +1,7 @@ -Constructing path queries -######################### +Creating path queries +##################### + +You can create path queries to visualize the flow of information through a codebase. Overview ======== @@ -24,7 +26,7 @@ For more language-specific information on analyzing data flow, see: - :doc:`Analyzing data flow in C# <../csharp/dataflow>` - :doc:`Analyzing data flow in Java <../java/dataflow>` - :doc:`Analyzing data flow in JavaScript/TypeScript <../javascript/dataflow>` -- :doc:`Taint tracking and data flow analysis in Python <../python/taint-tracking>` +- :doc:`Analyzing data flow and tracking tainted data in Python <../python/taint-tracking>` Path query examples ******************* @@ -95,7 +97,7 @@ Path query metadata ******************* Path query metadata must contain the property ``@kind path-problem``–this ensures that query results are interpreted and displayed correctly. -The other metadata requirements depend on how you intend to run the query. See the section on query metadata in :doc:`Introduction to query files ` for further information. +The other metadata requirements depend on how you intend to run the query. For more information, see `Query metadata `__. Generating path explanations **************************** @@ -185,11 +187,11 @@ Each result generated by your query is displayed at a single location in the sam The ``element`` that you select in the first column depends on the purpose of the query and the type of issue that it is designed to find. This is particularly important for security issues. For example, if you believe the ``source`` value to be globally invalid or malicious it may be best to display the alert at the ``source``. In contrast, you should consider displaying the alert at the ``sink`` if you believe it is the element that requires sanitization. -The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For further information, see :doc:`Defining 'select' statements `. +The alert message defined in the final column in the ``select`` statement can be developed to give more detail about the alert or path found by the query using links and placeholders. For more information, see :doc:`Defining the results of a query `. What next? ********** -- Take a look at the path queries for `C/C++ `__, `C# `__, `Java `__, `JavaScript `__, and `Python `__ to see examples of the queries included in the Semmle tools. +- Take a look at the path queries for `C/C++ `__, `C# `__, `Java `__, `JavaScript `__, and `Python `__ to see examples of these queries. - Explore the `query cookbooks `__ to see how to access the basic language elements contained in the CodeQL libraries. - For a full list of resources to help you learn CodeQL, including beginner tutorials and language-specific examples, visit `Learning CodeQL `__. diff --git a/docs/language/learn-ql/writing-queries/query-help.rst b/docs/language/learn-ql/writing-queries/query-help.rst index c3692b7fac0..89cad6528c6 100644 --- a/docs/language/learn-ql/writing-queries/query-help.rst +++ b/docs/language/learn-ql/writing-queries/query-help.rst @@ -1,5 +1,7 @@ -Query help reference -******************** +Query help files +**************** + +Query help files tell users the purpose of a query, and recommend how to solve the potential problem the query finds. This topic provides detailed information on the structure of query help files. For more information about how to write useful query help in a style that is consistent with the standard CodeQL queries, see the `Query help style guide `__ on GitHub. @@ -24,7 +26,7 @@ Each query help file provides detailed information about the purpose and use of Structure ========= -Query help files are written using an XML format called Qhelp (``.qhelp``). Query help files must have the same base name as the query they describe, and must be located in the same directory. The basic structure is as follows: +Query help files are written using a custom XML format, and stored in a file with a ``.qhelp`` extension. Query help files must have the same base name as the query they describe, and must be located in the same directory. The basic structure is as follows: .. code-block:: xml @@ -42,32 +44,32 @@ Section-level elements Section-level elements are used to group the information in the help file into sections. Many sections have a heading, either defined by a ``title`` attribute or a default value. The following section-level elements are optional child elements of the ``qhelp`` element. -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| Element | Attributes | Children | Purpose of section | -+====================+====================================+========================+===============================================================================================================================================+ -| ``example`` | None | Any block element | Demonstrate an example of code that violates the rule implemented by the query with guidance on how to fix it. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``fragment`` | None | Any block element | See :ref:`Qhelp inclusion ` below. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``hr`` | None | None | A horizontal rule. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``include`` | ``src`` The Qhelp file to include. | None | Include a Qhelp file at the location of this element. See :ref:`Qhelp inclusion ` below. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``overview`` | None | Any block element | Overview of the purpose of the query. Typically this is the first section in a query document. No heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``recommendation`` | None | Any block element | Recommend how to address any alerts that this query identifies. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``references`` | None | ``li`` elements | Reference list. Typically this is the last section in a query document. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ -| ``semmleNotes`` | None | Any block element | Semmle-specific notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | -+--------------------+------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| Element | Attributes | Children | Purpose of section | ++====================+=========================================+========================+===============================================================================================================================================+ +| ``example`` | None | Any block element | Demonstrate an example of code that violates the rule implemented by the query with guidance on how to fix it. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``fragment`` | None | Any block element | See :ref:`Query help inclusion ` below. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``hr`` | None | None | A horizontal rule. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion ` below. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``overview`` | None | Any block element | Overview of the purpose of the query. Typically this is the first section in a query document. No heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``recommendation`` | None | Any block element | Recommend how to address any alerts that this query identifies. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``references`` | None | ``li`` elements | Reference list. Typically this is the last section in a query document. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``section`` | ``title`` Title of the section | Any block element | General-purpose section with a heading defined by the ``title`` attribute. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ +| ``semmleNotes`` | None | Any block element | Implementation notes about the query. This section is used only for queries that implement a rule defined by a third party. Default heading. | ++--------------------+-----------------------------------------+------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------+ Block elements ============== -The following elements are optional child elements of the ``section``, ``example``, ``fragment``, ``recommendation``, ``overview`` and ``semmleNotes`` elements. +The following elements are optional child elements of the ``section``, ``example``, ``fragment``, ``recommendation``, ``overview``, and ``semmleNotes`` elements. .. table:: :widths: 7 20 10 25 @@ -82,7 +84,7 @@ The following elements are optional child elements of the ``section``, ``example | | | ``height`` Optional, height of the image. | | | | | | ``width`` Optional, the width of the image. | | | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | ``include`` | ``src`` The Qhelp file to include. | None | Include a Qhelp file at the location of this element. See :ref:`Qhelp inclusion ` below for more information. | + | ``include`` | ``src`` The query help file to include. | None | Include a query help file at the location of this element. See :ref:`Query help inclusion ` below for more information. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ``ol`` | None | ``li`` | Display an ordered list. See List elements below. | +----------------+----------------------------------------------------------+--------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -103,12 +105,12 @@ The following elements are optional child elements of the ``section``, ``example List elements ============= -Qhelp files support two types of block elements for lists: ``ul`` and ``ol``. Both block elements support only one child elements of the type ``li``. Each ``li`` element contains either inline content or a block element. +Query help files support two types of block elements for lists: ``ul`` and ``ol``. Both block elements support only one child elements of the type ``li``. Each ``li`` element contains either inline content or a block element. Table elements ============== -The ``table`` block element is used to include a table in a Qhelp file. Each table includes a number of rows, each of which includes a number of cells. The data in the cells will be rendered as a grid. +The ``table`` block element is used to include a table in a query help file. Each table includes a number of rows, each of which includes a number of cells. The data in the cells will be rendered as a grid. +-----------+------------+--------------------+-------------------------------------------+ | Element | Attributes | Children | Purpose | @@ -157,12 +159,12 @@ Inline content is used to define the content for paragraphs, list items, table c .. _qhelp-inclusion: -Qhelp inclusion -=============== +Query help inclusion +==================== -To enable the reuse of content between different help topics, shared content can be stored in one Qhelp file and then included in a number of other Qhelp files using the ``include`` element. The shared content can stored either in the same directory as the including files, or in ``SEMMLE_DIST/docs/include``. +To reuse content between different help topics, you can store shared content in one query help file and then include it in a number of other query help files using the ``include`` element. The shared content can be stored either in the same directory as the including files, or in ``SEMMLE_DIST/docs/include``. -The ``include`` element can be used as a section or block element, the content of the Qhelp file defined by the ``src`` attribute must contain elements that are appropriate to the location of the ``include`` element. +The ``include`` element can be used as a section or block element. The content of the query help file defined by the ``src`` attribute must contain elements that are appropriate to the location of the ``include`` element. Section-level include elements ------------------------------ @@ -175,7 +177,7 @@ Section-level ``include`` elements can be located beneath the top-level ``qhelp` -In this example, the `XSS.qhelp `__ file must conform to the standard for a full Qhelp file as described above. That is, the ``qhelp`` element may only contain non-``fragment``, section-level elements. +In this example, the `XSS.qhelp `__ file must conform to the standard for a full query help file as described above. That is, the ``qhelp`` element may only contain non-``fragment``, section-level elements. Block-level include elements ---------------------------- diff --git a/docs/language/learn-ql/writing-queries/query-metadata.rst b/docs/language/learn-ql/writing-queries/query-metadata.rst index 51af3018fdd..362b3c54405 100644 --- a/docs/language/learn-ql/writing-queries/query-metadata.rst +++ b/docs/language/learn-ql/writing-queries/query-metadata.rst @@ -1,5 +1,10 @@ -Query metadata -============== +Metadata for CodeQL queries +=========================== + +Metadata tells users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. + +About query metadata +-------------------- Any query that is run as part of an analysis includes a number of properties, known as query metadata. Metadata is included at the top of each query file as the content of a `QLDoc `__ comment. For alerts and path queries, this metadata tells LGTM and the CodeQL `extension for VS Code `__ how to handle the query and display its results correctly. @@ -10,31 +15,31 @@ You can also add metric queries to LGTM, but the results are not shown. To see t Note - The exact metadata requirement depends on how you are going to run your query. For more information, see the section on query metadata in :doc:`Introduction to query files `. + The exact metadata requirement depends on how you are going to run your query. For more information, see the section on query metadata in :doc:`About CodeQL queries `. Core properties --------------- The following properties are supported by all query files: -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Property | Value | Description | -+=======================+===========================+=============================================================================================================================================================================================================================================================================================================================================================================================================================================================================+ -| ``@description`` | ```` | A sentence or short paragraph to describe the purpose of the query and *why* the result is useful or important. The description is written in plain text, and uses single quotes (``'``) to enclose code elements. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@id`` | ```` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``/``. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`Introduction to query files ` | -| | | ``path-problem`` | | -| | | ``metric`` | | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@name`` | ```` | A statement that defines the label of the query. The name is written in plain text, and uses single quotes (``'``) to enclose code elements. | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| ``@tags`` | | ``correctness`` | These tags group queries together in broad categories to make it easier to search for them and identify them. You can also `filter alerts `__ based on their tags. In addition to the common tags listed here, there are also a number of more specific categories. For more information about some of the tags that are already used and what they mean, see `Query tags `__. | -| | | ``mantainability`` | | -| | | ``readability`` | | -| | | ``security`` | | -+-----------------------+---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Property | Value | Description | ++=======================+===========================+==============================================================================================================================================================================================================================================================================================================================================================================+ +| ``@description`` | ```` | A sentence or short paragraph to describe the purpose of the query and *why* the result is useful or important. The description is written in plain text, and uses single quotes (``'``) to enclose code elements. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@id`` | ```` | A sequence of words composed of lowercase letters or digits, delimited by ``/`` or ``-``, identifying and classifying the query. Each query must have a **unique** ID. To ensure this, it may be helpful to use a fixed structure for each ID. For example, the standard LGTM queries have the following format: ``/``. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@kind`` | | ``problem`` | Identifies the query is an alert (``@kind problem``), a path (``@kind path-problem``), or a metric (``@kind metric``). For further information on these query types, see :doc:`About CodeQL queries `. | +| | | ``path-problem`` | | +| | | ``metric`` | | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@name`` | ```` | A statement that defines the label of the query. The name is written in plain text, and uses single quotes (``'``) to enclose code elements. | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| ``@tags`` | | ``correctness`` | These tags group queries together in broad categories to make it easier to search for them and identify them. In addition to the common tags listed here, there are also a number of more specific categories. For more information about some of the tags that are already used and what they mean, see `Query tags `__ on LGTM.com. | +| | | ``mantainability`` | | +| | | ``readability`` | | +| | | ``security`` | | ++-----------------------+---------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ Additional properties for problem and path-problem queries diff --git a/docs/language/learn-ql/writing-queries/select-statement.rst b/docs/language/learn-ql/writing-queries/select-statement.rst index c974f8a21d6..5531a958e3e 100644 --- a/docs/language/learn-ql/writing-queries/select-statement.rst +++ b/docs/language/learn-ql/writing-queries/select-statement.rst @@ -1,5 +1,10 @@ -Defining 'select' statements -============================ +Defining the results of a query +=============================== + +You can control how analysis results are displayed in source code by modifying a query's ``select`` statement. + +About query results +------------------- The information contained in the results of a query is controlled by the ``select`` statement. Part of the process of developing a useful query is to make the results clear and easy for other users to understand. When you write your own queries in the query console or in the CodeQL `extension for VS Code `__ there are no constraints on what can be selected. @@ -22,7 +27,7 @@ If you look at some of the LGTM queries, you'll see that they can select extra e Note - An in-depth discussion of ``select`` statements for path and metric queries is not included in this topic. However, you can develop the string column of the ``select`` statement in the same way as for alert queries. For more specific information about path queries, see :doc:`Constructing path queries `. + An in-depth discussion of ``select`` statements for path and metric queries is not included in this topic. However, you can develop the string column of the ``select`` statement in the same way as for alert queries. For more specific information about path queries, see :doc:`Creating path queries `. Developing a select statement ----------------------------- diff --git a/docs/language/learn-ql/writing-queries/writing-queries.rst b/docs/language/learn-ql/writing-queries/writing-queries.rst index e08048953c0..bdf702ded1c 100644 --- a/docs/language/learn-ql/writing-queries/writing-queries.rst +++ b/docs/language/learn-ql/writing-queries/writing-queries.rst @@ -1,57 +1,25 @@ -Writing CodeQL queries -###################### +CodeQL queries +############## -If you are familiar with CodeQL, you can modify the existing queries or write custom queries to analyze, improve, and secure your own projects. Get started by reading the information for query writers and viewing the examples provided below. - -Information for query writers -***************************** +CodeQL queries are used in code scanning analyses to find problems in source code, including potential security vulnerabilities. .. toctree:: - :glob: :hidden: introduction-to-queries - path-queries - ../intro-to-data-flow - select-statement - ../locations - debugging-queries - - -Visit `Learning CodeQL `__ to find basic information about CodeQL. This includes information about the underlying query language QL, as well as help and advice on writing queries for specific programming languages. -To learn more about the structure of query files, the key information to include when writing your own queries, and how to format them for clarity and consistency, see the following topics: - -- :doc:`Introduction to query files `–an introduction to the information contained in a basic query file. -- :doc:`Constructing path queries `–a quick guide to structuring path queries to use in security research. -- :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`–a brief introduction to modeling data flow using CodeQL. -- :doc:`Defining 'select' statements `–further detail on developing query alert messages to provide extra information in your query results. -- :doc:`Locations and strings for CodeQL entities <../locations>`–further detail on providing location information in query results. -- `CodeQL style guide on GitHub `__–a guide to formatting your queries for consistency and clarity. - -Viewing existing CodeQL queries -******************************* - -The easiest way to get started writing your own queries is to modify an existing query. To see these queries, or to try out the CodeQL query cookbooks, visit `Exploring CodeQL queries `__. -You can also find all the CodeQL queries in our `open source repository on GitHub `__. - -You can also find examples of queries developed to find security vulnerabilities and bugs in open-source software projects on the `GitHub Security Lab website `__ and in the associated `repository `__. - -Contributing queries -******************** - -.. toctree:: - :glob: - :hidden: - query-metadata query-help + select-statement + ../locations + ../intro-to-data-flow + path-queries + debugging-queries -Contributions to the standard queries and libraries are very welcome–see our `contributing guidelines `__ for further information. -If you are contributing a query to the open source GitHub repository, writing a custom query for LGTM, or using a custom query in an analysis with our command-line tools, then you need to include extra metadata in your query to ensure that the query results are interpreted and displayed correctly. See the following topics for more information on query metadata: - -.. TODO: Change "command-line tools" to a link to the CodeQL CLI? - -- :doc:`Query metadata reference ` -- `Query metadata style guide on GitHub `__ - -Query contributions to the open source GitHub repository may also have an accompanying query help file to provide information about their purpose for other users. For more information on writing query help, see the `Query help style guide on GitHub `__ and the :doc:`Query help reference `. \ No newline at end of file +- :doc:`About CodeQL queries `: CodeQL queries are used to analyze code for issues related to security, correctness, maintainability, and readability. +- :doc:`Metadata for CodeQL queries `: Metadata tells users important information about CodeQL queries. You must include the correct query metadata in a query to be able to view query results in source code. +- :doc:`Query help files `: Query help files tell users the purpose of a query, and recommend how to solve the potential problem the query finds. +- :doc:`Defining the results of a query `: You can control how analysis results are displayed in source code by modifying a query's ``select`` statement. +- :doc:`Providing locations in CodeQL queries <../locations>`: CodeQL includes mechanisms for extracting the location of elements in a codebase. Use these mechanisms when writing custom CodeQL queries and libraries to help display information to users. +- :doc:`About data flow analysis <../intro-to-data-flow>`: Data flow analysis is used to compute the possible values that a variable can hold at various points in a program, determining how those values propagate through the program and where they are used. +- :doc:`Creating path queries `: You can create path queries to visualize the flow of information through a codebase. +- :doc:`Troubleshooting query performance `: Improve the performance of your CodeQL queries by following a few simple guidelines. diff --git a/docs/language/learn-ql/about-ql.rst b/docs/language/ql-handbook/about-the-ql-language.rst similarity index 82% rename from docs/language/learn-ql/about-ql.rst rename to docs/language/ql-handbook/about-the-ql-language.rst index 5f5362b8fd8..8cb38d05df3 100644 --- a/docs/language/learn-ql/about-ql.rst +++ b/docs/language/ql-handbook/about-the-ql-language.rst @@ -1,17 +1,15 @@ -About QL -======== +About the QL language +###################### -This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see :doc:`Introduction to QL ` and :doc:`Learning CodeQL <../index>`. - -QL is a declarative, object-oriented query language that is optimized to enable efficient analysis of hierarchical data structures, in particular, databases representing software artifacts. - -The queries and metrics used in LGTM are implemented using CodeQL, which uses QL to analyze code. This ensures that they can be extended or revised easily to keep up with changes in definitions of best coding practice. We continually improve existing queries as we work towards the ultimate goal of 100% precision. - -You can write queries to identify security vulnerabilities, find coding errors and bugs, or find code that breaks your team's guidelines for best practice. You can also create customized versions of the default queries to accommodate a new framework. +QL is the powerful query language that underlies CodeQL, which is used to analyze code. About query languages and databases ----------------------------------- +This section is aimed at users with a background in general purpose programming as well as in databases. For a basic introduction and information on how to get started, see `Learning CodeQL `__. + +QL is a declarative, object-oriented query language that is optimized to enable efficient analysis of hierarchical data structures, in particular, databases representing software artifacts. + A database is an organized collection of data. The most commonly used database model is a relational model which stores data in tables and SQL (Structured Query Language) is the most commonly used query language for relational databases. The purpose of a query language is to provide a programming platform where you can ask questions about information stored in a database. A database management system manages the storage and administration of data and provides the querying mechanism. A query typically refers to the relevant database entities and specifies various conditions (called predicates) that must be satisfied by the results. Query evaluation involves checking these predicates and generating the results. Some of the desirable properties of a good query language and its implementation include: @@ -41,6 +39,11 @@ When you write this process in QL, it closely resembles the above structure. Not result = count(getADescendant(p)) } +For more information about the important concepts and syntactic constructs of QL, see the individual reference topics such as :doc:`Expressions ` and :doc:`Recursion `. +The explanations and examples help you understand how the language works, and how to write more advanced QL code. + +For formal specifications of the QL language and QLDoc comments, see the :doc:`QL language specification ` and :doc:`QLDoc comment specification `. + QL and object orientation ------------------------- @@ -56,12 +59,10 @@ Here are a few prominent conceptual and functional differences between general p - QL's set-based semantics makes it very natural to process collections of values without having to worry about efficiently storing, indexing and traversing them. - In object oriented programming languages, instantiating a class involves creating an object by allocating physical memory to hold the state of that instance of the class. In QL, classes are just logical properties describing sets of already existing values. -These topics are discussed in detail in the `QL language handbook `__. +Further reading +--------------- -References ----------- - -Academic references available from the `Semmle website `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: +`Academic references `__ also provide an overview of QL and its semantics. Other useful references on database query languages and Datalog: - `Database theory: Query languages `__ - `Logic Programming and Databases book - Amazon page `__ diff --git a/docs/language/ql-handbook/aliases.rst b/docs/language/ql-handbook/aliases.rst index 88675370081..03bdc835a30 100644 --- a/docs/language/ql-handbook/aliases.rst +++ b/docs/language/ql-handbook/aliases.rst @@ -4,8 +4,9 @@ Aliases ####### -An alias is an alternative name for an existing QL entity. Once you've defined an alias, -you can use that new name to refer to the entity in the current module's :ref:`namespace `. +An alias is an alternative name for an existing QL entity. + +Once you've defined an alias, you can use that new name to refer to the entity in the current module's :ref:`namespace `. Defining an alias ***************** diff --git a/docs/language/ql-handbook/annotations.rst b/docs/language/ql-handbook/annotations.rst index 8673b8194f6..9177a4197b6 100644 --- a/docs/language/ql-handbook/annotations.rst +++ b/docs/language/ql-handbook/annotations.rst @@ -4,6 +4,7 @@ Annotations ########### An annotation is a string that you can place directly before the declaration of a QL entity or name. + For example, to declare a module ``M`` as private, you could use:: private module M { @@ -248,7 +249,7 @@ Compiler pragmas The following compiler pragmas affect the compilation and optimization of queries. You should avoid using these annotations unless you experience significant performance issues. -Before adding pragmas to your code, contact Semmle to describe the performance problems. +Before adding pragmas to your code, contact GitHub to describe the performance problems. That way we can suggest the best solution for your problem, and take it into account when improving the QL optimizer. @@ -291,7 +292,7 @@ optimization on a predicate. This kind of optimization involves taking information from the context of a predicate :ref:`call ` and pushing it into the body of a predicate. This is usually beneficial, so you shouldn't use the ``pragma[nomagic]`` annotation unless recommended to do so -by Semmle. +by GitHub. Note that ``nomagic`` implies ``noinline``. @@ -302,7 +303,7 @@ The ``pragma[noopt]`` annotation is used to prevent the QL optimizer from optimi predicate, except when it's absolutely necessary for compilation and evaluation to work. This is rarely necessary and you should not use the ``pragma[noopt]`` annotation unless -recommended to do so by Semmle, for example, to help resolve performance issues. +recommended to do so by GitHub, for example, to help resolve performance issues. When you use this annotation, be aware of the following issues: diff --git a/docs/language/ql-handbook/conf.py b/docs/language/ql-handbook/conf.py index 1b4887c0f06..10bda010a7e 100644 --- a/docs/language/ql-handbook/conf.py +++ b/docs/language/ql-handbook/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# QL language handbook build configuration file, created by +# QL language reference build configuration file, created by # sphinx-quickstart on Wed Feb 28 12:01:34 2018. # # This file is execfile()d with the current directory set to its @@ -17,9 +17,10 @@ ################################################################################ # -# Modified 22052019. - -# The configuration values below are specific to the QL handbook +# Modified 02042020 to rename "handbook" to "reference". +# This Sphinx project now contains both the handbook articles and the specifications. +# +# The configuration values below are specific to the QL language reference project. # To amend html_theme_options, update version/release number, or add more sphinx extensions, # refer to code/documentation/ql-documentation/global-sphinx-files/global-conf.py @@ -41,7 +42,7 @@ highlight_language = 'ql' master_doc = 'index' # Project-specific information. -project = u'QL language handbook' +project = u'QL language reference' # The version info for this project, if different from version and release in main conf.py file. # The short X.Y version. @@ -53,10 +54,10 @@ project = u'QL language handbook' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = 'QL language handbook' +html_title = 'QL language reference' # Output file base name for HTML help builder. -htmlhelp_basename = 'QL language handbook' +htmlhelp_basename = 'QL language reference' # -- Currently unused, but potentially useful, configs-------------------------------------- diff --git a/docs/language/ql-handbook/evaluation.rst b/docs/language/ql-handbook/evaluation.rst index 251b951c0e1..42520f634a2 100644 --- a/docs/language/ql-handbook/evaluation.rst +++ b/docs/language/ql-handbook/evaluation.rst @@ -3,6 +3,8 @@ Evaluation of QL programs ######################### +A QL program is evaluated in a number of different steps. + Process ******* diff --git a/docs/language/ql-handbook/expressions.rst b/docs/language/ql-handbook/expressions.rst index d455a95ed1f..729bd9e4876 100644 --- a/docs/language/ql-handbook/expressions.rst +++ b/docs/language/ql-handbook/expressions.rst @@ -3,11 +3,10 @@ Expressions ########### -An expression evaluates to a set of values in QL. For example, the expression ``1 + 2`` -evaluates to the integer ``3`` and the expression ``"QL"`` evaluates to the string ``"QL"``. +An expression evaluates to a set of values and has a type. -A valid expression also has a :ref:`type `. -In the above examples, ``1 + 2`` has type ``int`` and ``"QL"`` has type ``string``. +For example, the expression ``1 + 2`` +evaluates to the integer ``3`` and the expression ``"QL"`` evaluates to the string ``"QL"``. ``1 + 2`` has :ref:`type ` ``int`` and ``"QL"`` has type ``string``. The following sections describe the expressions that are available in QL. @@ -296,6 +295,22 @@ The following aggregates are available in QL: evaluates to the empty set (instead of defaulting to ``0`` or the empty string). This is useful if you're only interested in results where the aggregation body is non-trivial. +.. index:: unique + +- ``unique``: This aggregate depends on the values of ```` over all possible assignments to + the aggregation variables. If there is a unique value of ```` over the aggregation variables, + then the aggregate evaluates to that value. + Otherwise, the aggregate has no value. + + For example, the following query returns the positive integers ``1``, ``2``, ``3``, ``4``, ``5``. + For negative integers ``x``, the expressions ``x`` and ``x.abs()`` have different values, so the + value for ``y`` in the aggregate expression is not uniquely determined. :: + + from int x + where x in [-5 .. 5] and x != 0 + select unique(int y | y = x or y = x.abs() | y) + + The ``unique`` aggregate is supported from release 2.1.0 of the CodeQL CLI, and release 1.24 of LGTM Enterprise. Evaluation of aggregates ======================== diff --git a/docs/language/ql-handbook/formulas.rst b/docs/language/ql-handbook/formulas.rst index 45ef1302fb7..cedbfa4a4cf 100644 --- a/docs/language/ql-handbook/formulas.rst +++ b/docs/language/ql-handbook/formulas.rst @@ -3,10 +3,9 @@ Formulas ######## -Formulas define logical relations between the :ref:`free variables ` used in -:ref:`expressions `. +Formulas define logical relations between the free variables used in expressions. -Depending on the values assigned to those free variables, a formula can be true or false. +Depending on the values assigned to those :ref:`free variables `, a formula can be true or false. When a formula is true, we often say that the formula *holds*. For example, the formula ``x = 4 + 5`` holds if the value ``9`` is assigned to ``x``, but it doesn't hold for other assignments to ``x``. diff --git a/docs/language/ql-handbook/index.rst b/docs/language/ql-handbook/index.rst index 701d7d02237..ec4ab6d671e 100644 --- a/docs/language/ql-handbook/index.rst +++ b/docs/language/ql-handbook/index.rst @@ -1,29 +1,12 @@ -QL language handbook -#################### +QL language reference +##################### -Welcome to the QL language handbook! - -This document describes the main features of the QL language. The explanations and examples -help you understand how the language works, and how to write more advanced QL code. - -Each section describes an important concept or syntactic construct of QL. For an overview, see -the table of contents below. - -If you are just getting started with QL, see `Learning CodeQL `_ -for a list of the available resources. - -.. index:: specification - -For a formal specification of the QL language, see the `QL language specification -`_. - -Table of contents -***************** +Learn all about QL, the powerful query language that underlies the code scanning tool CodeQL. .. toctree:: - :numbered: 3 - :maxdepth: 3 + :maxdepth: 1 + about-the-ql-language predicates queries types @@ -37,9 +20,5 @@ Table of contents lexical-syntax name-resolution evaluation - -Index and search -**************** - -* :ref:`genindex` -* :ref:`search` + language + qldoc \ No newline at end of file diff --git a/docs/language/ql-spec/language.rst b/docs/language/ql-handbook/language.rst similarity index 99% rename from docs/language/ql-spec/language.rst rename to docs/language/ql-handbook/language.rst index ab4b308b367..1446e18a4f8 100644 --- a/docs/language/ql-spec/language.rst +++ b/docs/language/ql-handbook/language.rst @@ -1,12 +1,16 @@ QL language specification ========================= +This is a formal specification for the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. + +.. This ``highlight`` directive prevents code blocks in this file being highlighted as QL (the default language for this Sphinx project). + +.. highlight:: none + Introduction ------------ -This document specifies the QL language. It provides a comprehensive reference for terminology, syntax, and other technical details about QL. - -QL is a query language for Semmle databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. +QL is a query language for CodeQL databases. The data is relational: named relations hold sets of tuples. The query language is a dialect of Datalog, using stratified semantics, and it includes object-oriented classes. Notation -------- @@ -998,7 +1002,7 @@ For casts between the primitive ``float`` and ``int`` types, the above rule mean Postfix casts ~~~~~~~~~~~~~ -*Available from Semmle 1.9.4 onward.* A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: +A postfix cast is a primary expression followed by a dot and then a class or primitive type in parentheses: :: @@ -1058,6 +1062,7 @@ An aggregation can be written in one of two forms: aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" @@ -1098,7 +1103,7 @@ The typing environment for ordering directives is obtained by taking the typing The number and types of the aggregation expressions are restricted as follows: -- A ``max``, ``min`` or ``rank`` aggregation must have a single expression. +- A ``max``, ``min``, ``rank`` or ``unique`` aggregation must have a single expression. - The type of the expression in a ``max``, ``min`` or ``rank`` aggregation without an ordering directive expression must be an orderable type. - A ``count`` or ``strictcount`` aggregation must not have an expression. - A ``sum``, ``strictsum`` or ``avg`` aggregation must have a single aggregation expression, which must have a type which is a subtype of ``float``. @@ -1140,6 +1145,8 @@ The values of the aggregation expression are given by applying the aggregation f - If the aggregation id is ``strictconcat``, then the result is the same as for ``concat`` except in the case where there are no aggregation tuples in which case the aggregation has no value. + - If the aggregation id is ``unique``, then the result is the value of the aggregation variable if there is precisely one such value. Otherwise, the aggregation has no value. + Any ~~~ @@ -1976,7 +1983,8 @@ The complete grammar for QL is as follows: aggregation ::= aggid ("[" expr "]")? "(" (var_decls)? ("|" (formula)? ("|" as_exprs ("order" "by" aggorderbys)?)?)? ")" | aggid ("[" expr "]")? "(" as_exprs ("order" "by" aggorderbys)? ")" - + | "unique" "(" var_decls "|" (formula)? ("|" as_exprs)? ")" + aggid ::= "avg" | "concat" | "count" | "max" | "min" | "rank" | "strictconcat" | "strictcount" | "strictsum" | "sum" aggorderbys ::= aggorderby ("," aggorderby)* diff --git a/docs/language/ql-handbook/lexical-syntax.rst b/docs/language/ql-handbook/lexical-syntax.rst index d5f152e829e..481b0bf87ea 100644 --- a/docs/language/ql-handbook/lexical-syntax.rst +++ b/docs/language/ql-handbook/lexical-syntax.rst @@ -3,10 +3,10 @@ Lexical syntax ############## +The QL syntax includes different kinds of keywords, identifiers, and comments. + For an overview of the lexical syntax, see `Lexical syntax -`_ -in the QL language specification. In particular, you can find the list of QL keywords, the -different kinds of identifiers, and a description of comments. +`_ in the QL language specification. .. index:: comment, QLDoc .. _comments: @@ -19,7 +19,7 @@ All standard one-line and multiline comments, as described in the `QL language s compiler and are only visible in the source code. You can also write another kind of comment, namely **QLDoc comments**. These comments describe QL entities and are displayed as pop-up information in QL editors. For information about QLDoc -comments, see the `QLDoc specification `_. +comments, see the `QLDoc comment specification `_. The following example uses these three different kinds of comments:: diff --git a/docs/language/ql-handbook/name-resolution.rst b/docs/language/ql-handbook/name-resolution.rst index 6c6bd47e6fe..3e44140640e 100644 --- a/docs/language/ql-handbook/name-resolution.rst +++ b/docs/language/ql-handbook/name-resolution.rst @@ -3,6 +3,8 @@ Name resolution ############### +The QL compiler resolves names to program elements. + As in other programming languages, there is a distinction between the names used in QL code, and the underlying QL entities they refer to. @@ -240,7 +242,7 @@ and the global namespaces. (You can think of global namespaces as the enclosing Let's see what the module, type, and predicate namespaces look like in a concrete example: For example, you could define a library module ``Villagers`` containing some of the classes and predicates that -were defined in the `QL detective tutorials `_: +were defined in the `QL tutorials `_: **Villagers.qll** diff --git a/docs/language/ql-spec/qldoc.rst b/docs/language/ql-handbook/qldoc.rst similarity index 81% rename from docs/language/ql-spec/qldoc.rst rename to docs/language/ql-handbook/qldoc.rst index 62987574c12..d2ca924598e 100644 --- a/docs/language/ql-spec/qldoc.rst +++ b/docs/language/ql-handbook/qldoc.rst @@ -1,7 +1,12 @@ -QLDoc specification -=================== +QLDoc comment specification +=========================== -This document is a specification for QLDoc comments in QL source files. +This document is a formal specification for QLDoc comments. + +About QLDoc comments +-------------------- + +You can provide documentation for a QL entity by adding a QLDoc comment in the source file. The QLDoc comment is displayed as pop-up information in QL editors, for example when you hover over a predicate name. Notation -------- @@ -36,7 +41,7 @@ Content The content of a QLDoc comment is interpreted as standard Markdown, with the following extensions: -- Fenced code blocks using \`s. +- Fenced code blocks using backticks. - Automatic interpretation of links and email addresses. - Use of appropriate characters for ellipses, dashes, apostrophes, and quotes. diff --git a/docs/language/ql-handbook/queries.rst b/docs/language/ql-handbook/queries.rst index 1c21482af35..c6ef62d6b13 100644 --- a/docs/language/ql-handbook/queries.rst +++ b/docs/language/ql-handbook/queries.rst @@ -4,8 +4,7 @@ Queries ####### -Queries are the output of a QL program: they evaluate to sets of results. Indeed, we -often refer to the whole QL program as a *query*. +Queries are the output of a QL program. They evaluate to sets of results. There are two kinds of queries. For a given :ref:`query module `, the queries in that module are: - The :ref:`select clause `, if any, defined in that module. @@ -13,6 +12,8 @@ There are two kinds of queries. For a given :ref:`query module `, :ref:`namespace `. That is, they can be defined in the module itself, or imported from a different module. +We often also refer to the whole QL program as a query. + .. index:: from, where, select .. _select-clauses: diff --git a/docs/language/ql-handbook/types.rst b/docs/language/ql-handbook/types.rst index dfa7a8cd30f..92ac01bd42b 100644 --- a/docs/language/ql-handbook/types.rst +++ b/docs/language/ql-handbook/types.rst @@ -5,7 +5,9 @@ Types ##### -QL is a statically typed language, so each variable must have a declared **type**. A type is a set of values. +QL is a statically typed language, so each variable must have a declared type. + +A type is a set of values. For example, the type ``int`` is the set of integers. Note that a value can belong to more than one of these sets, which means that it can have more than one type. diff --git a/docs/language/ql-handbook/variables.rst b/docs/language/ql-handbook/variables.rst index 25b4fff1ad2..a74d492b61c 100644 --- a/docs/language/ql-handbook/variables.rst +++ b/docs/language/ql-handbook/variables.rst @@ -5,11 +5,11 @@ Variables ######### Variables in QL are used in a similar way to variables in algebra or logic. They represent sets -of values, and those values are usually restricted by a :ref:`formula `. +of values, and those values are usually restricted by a formula. This is different from variables in some other programming languages, where variables represent memory locations that may contain data. That data can also change over time. For example, in -QL, ``n = n + 1`` is an equality formula that holds only +QL, ``n = n + 1`` is an equality :ref:`formula ` that holds only if ``n`` is equal to ``n + 1`` (so in fact it does not hold for any numeric value). In Java, ``n = n + 1`` is not an equality, but an assignment that changes the value of ``n`` by adding ``1`` to the current value. diff --git a/docs/language/ql-spec/index.rst b/docs/language/ql-spec/index.rst index 4cbdc834936..cba06a87746 100644 --- a/docs/language/ql-spec/index.rst +++ b/docs/language/ql-spec/index.rst @@ -1,24 +1,5 @@ -QL specifications -################# +README +###### -.. index:: specification - - -For a formal specification of the QL language, including a description of syntax, terminology, and other technical details, please consult the QL language specification. - -For information on the terminology and syntax used in QLDoc comments, please consult the QLDoc specification. - -.. toctree:: - :maxdepth: 2 - - language - - qldoc - - -Search -****** - -.. * :ref:`genindex` - -* :ref:`search` +The specifications have moved to ``ql/docs/language/ql-handbook``. +See https://github.com/github/semmle-docs/issues/21 for details of the restructuring. \ No newline at end of file diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 6beff0b708e..7f398da8d4b 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -68,7 +68,7 @@ A simple CodeQL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference `__), see `Introduction to query files `__. In our example here, the first line of the query imports the `CodeQL library for C/C++ `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f93a619c142..66c41df44b0 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -68,7 +68,7 @@ A simple CodeQL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language reference `__), see `Introduction to query files `__. In our example here, the first line of the query imports the `CodeQL library for Java `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index 8d6a25afad7..f03c0300e25 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -101,7 +101,7 @@ Analysis overview .. note:: - Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. + CodeQL analysis works by extracting a queryable database from your project. For compiled languages, the tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. @@ -124,12 +124,12 @@ QL is: .. note:: - QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. + QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting the `QL language reference `__. The key features of QL are: - All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables. - The language is declarative–the user focuses on stating what they would like to find, and leaves the details of how to evaluate the query to the engine. - - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. + - The object-oriented layer allows us to develop rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. + - The database generated by the CodeQL tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download CodeQL databases from LGTM.com to query locally, by `running queries in your IDE `__. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index ed681b0398a..0bbb2c20ba4 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -111,8 +111,8 @@ So all references will need to be qualified (that is, ``DataFlow::Node``) A **module** is a way of organizing QL code by grouping together related predicates, classes, and (sub-)modules. They can be either explicitly declared or implicit. A query library implicitly declares a module with the same name as the QLL file. - For further information on libraries and modules in QL, see the chapter on `Modules `__ in the QL language handbook. - For further information on importing QL libraries and modules, see the chapter on `Name resolution `__ in the QL language handbook. + For further information on libraries and modules in QL, see the chapter on `Modules `__ in the QL language reference. + For further information on importing QL libraries and modules, see the chapter on `Name resolution `__ in the QL language reference. Data flow graph =============== diff --git a/docs/language/reusables/python-other-resources.rst b/docs/language/reusables/python-other-resources.rst new file mode 100644 index 00000000000..8e9482cf230 --- /dev/null +++ b/docs/language/reusables/python-other-resources.rst @@ -0,0 +1,3 @@ +- "`QL language reference `__" +- `Python cookbook queries `__ in the Semmle wiki +- `Python queries in action `__ on LGTM.com diff --git a/docs/language/support/conf.py b/docs/language/support/conf.py index 30d7b1a3028..e88bdfce1bb 100644 --- a/docs/language/support/conf.py +++ b/docs/language/support/conf.py @@ -80,4 +80,4 @@ htmlhelp_basename = 'Supported languages and frameworks' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['read-me-project.rst'] \ No newline at end of file +exclude_patterns = ['read-me-project.rst', 'reusables/*'] \ No newline at end of file diff --git a/docs/language/support/csharp-frameworks.csv b/docs/language/support/csharp-frameworks.csv deleted file mode 100644 index 28b0b3bb06c..00000000000 --- a/docs/language/support/csharp-frameworks.csv +++ /dev/null @@ -1,9 +0,0 @@ -Name, Category -ASP.NET, Web application framework -ASP.NET Core, Web application framework -ASP.NET Razor templates, Web application framework -EntityFramework, Database ORM -EntityFramework Core, Database ORM -Json.NET, Serialization -NHibernate, Database ORM -WinForms, User interface diff --git a/docs/language/support/framework-support.rst b/docs/language/support/framework-support.rst index 71455b983ec..37d54829475 100644 --- a/docs/language/support/framework-support.rst +++ b/docs/language/support/framework-support.rst @@ -12,40 +12,4 @@ The libraries and queries in version |version| have been explicitly checked agai .. There is currently no built-in support for libraries or frameworks for C/C++. -C# built-in support -================================ - -.. csv-table:: - :file: csharp-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - -Java built-in support -================================== - -.. csv-table:: - :file: java-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - - -JavaScript and TypeScript built-in support -======================================================= - -.. csv-table:: - :file: javascript-typescript-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto - - -Python built-in support -==================================== - -.. csv-table:: - :file: python-frameworks.csv - :header-rows: 1 - :class: fullWidthTable - :widths: auto +.. include:: reusables/frameworks.rst diff --git a/docs/language/support/java-frameworks.csv b/docs/language/support/java-frameworks.csv deleted file mode 100644 index 876d0ae111c..00000000000 --- a/docs/language/support/java-frameworks.csv +++ /dev/null @@ -1,13 +0,0 @@ -Name, Category -Hibernate, Database -iBatis / MyBatis, Database -Java Persistence API (JPA), Database -JDBC, Database -Protobuf, Serialization -Kryo deserialization, Serialization -SnakeYaml, Serialization -Spring JDBC, Database -Spring MVC, Web application framework -Struts, Web application framework -Thrift, RPC framework -XStream, Serialization diff --git a/docs/language/support/javascript-typescript-frameworks.csv b/docs/language/support/javascript-typescript-frameworks.csv deleted file mode 100644 index abed9dc5113..00000000000 --- a/docs/language/support/javascript-typescript-frameworks.csv +++ /dev/null @@ -1,23 +0,0 @@ -Name, Category -angularjs, HTML framework -axios, Network communicator -browser, Runtime environment -electron, Runtime environment -express, Server -hapi, Server -jquery, Utility library -koa, Server -lodash, Utility library -mongodb, Database -mssql, Database -mysql, Database -node, Runtime environment -postgres, Database -ramda, Utility library -react, HTML framework -request, Network communicator -sequelize, Database -socket.io, Network communicator -sqlite3, Database -superagent, Network communicator -underscore, Utility library diff --git a/docs/language/support/language-support.rst b/docs/language/support/language-support.rst index 1dea250d430..4aebb9957d6 100644 --- a/docs/language/support/language-support.rst +++ b/docs/language/support/language-support.rst @@ -10,18 +10,4 @@ Customers with any questions should contact their usual Semmle contact with any If you're not a customer yet, contact us at info@semmle.com with any questions you have about language and compiler support. -.. csv-table:: - :file: versions-compilers.csv - :header-rows: 1 - :widths: auto - :stub-columns: 1 - -.. container:: footnote-group - - .. [1] Support for the clang-cl compiler is preliminary. - .. [2] Support for the Arm Compiler (armcc) is preliminary. - .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. - .. [4] Builds that execute on Java 6 to 12 can be analyzed. The analysis understands Java 12 language features. - .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. - .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. - .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. +.. include:: reusables/versions-compilers.rst diff --git a/docs/language/support/python-frameworks.csv b/docs/language/support/python-frameworks.csv deleted file mode 100644 index 7a5e78d8756..00000000000 --- a/docs/language/support/python-frameworks.csv +++ /dev/null @@ -1,11 +0,0 @@ -Name, Category -Bottle, Web framework -CherryPy, Web framework -Django, Web application framework -Falcon, Web API framework -Flask, Microframework -Pyramid, Web application framework -Tornado, Web application framework and asynchronous networking library -Turbogears, Web framework -Twisted, Networking engine -WebOb, WSGI request library diff --git a/docs/language/support/reusables/frameworks.rst b/docs/language/support/reusables/frameworks.rst new file mode 100644 index 00000000000..1b8e85e60e2 --- /dev/null +++ b/docs/language/support/reusables/frameworks.rst @@ -0,0 +1,95 @@ +.. There is currently no built-in support for libraries or frameworks for C/C++. + +C# built-in support +================================ + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + ASP.NET, Web application framework + ASP.NET Core, Web application framework + ASP.NET Razor templates, Web application framework + EntityFramework, Database ORM + EntityFramework Core, Database ORM + Json.NET, Serialization + NHibernate, Database ORM + WinForms, User interface + +Java built-in support +================================== + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + Hibernate, Database + iBatis / MyBatis, Database + Java Persistence API (JPA), Database + JDBC, Database + Protobuf, Serialization + Kryo deserialization, Serialization + SnakeYaml, Serialization + Spring JDBC, Database + Spring MVC, Web application framework + Struts, Web application framework + Thrift, RPC framework + XStream, Serialization + +JavaScript and TypeScript built-in support +======================================================= + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + angularjs, HTML framework + axios, Network communicator + browser, Runtime environment + electron, Runtime environment + express, Server + hapi, Server + jquery, Utility library + koa, Server + lodash, Utility library + mongodb, Database + mssql, Database + mysql, Database + node, Runtime environment + postgres, Database + ramda, Utility library + react, HTML framework + request, Network communicator + sequelize, Database + socket.io, Network communicator + sqlite3, Database + superagent, Network communicator + underscore, Utility library + + + +Python built-in support +==================================== + +.. csv-table:: + :header-rows: 1 + :class: fullWidthTable + :widths: auto + + Name, Category + Bottle, Web framework + CherryPy, Web framework + Django, Web application framework + Falcon, Web API framework + Flask, Microframework + Pyramid, Web application framework + Tornado, Web application framework and asynchronous networking library + Turbogears, Web framework + Twisted, Networking engine + WebOb, WSGI request library diff --git a/docs/language/support/reusables/versions-compilers.rst b/docs/language/support/reusables/versions-compilers.rst new file mode 100644 index 00000000000..3b244e592bd --- /dev/null +++ b/docs/language/support/reusables/versions-compilers.rst @@ -0,0 +1,33 @@ +.. csv-table:: + :header-rows: 1 + :widths: auto + :stub-columns: 1 + + Language,Variants,Compilers,Extensions + C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), + + GNU extensions (up to GCC 9.2), + + Microsoft extensions (up to VS 2019), + + Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" + C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, + + .NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" + Go (aka Golang), "Go up to 1.14", "Go 1.11 or more recent", ``.go`` + Java,"Java 6 to 14 [4]_","javac (OpenJDK and Oracle JDK), + + Eclipse compiler for Java (ECJ) [5]_",``.java`` + JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" + Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` + TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" + +.. container:: footnote-group + + .. [1] Support for the clang-cl compiler is preliminary. + .. [2] Support for the Arm Compiler (armcc) is preliminary. + .. [3] In addition, support is included for the preview features of C# 8.0 and .NET Core 3.0. + .. [4] Builds that execute on Java 6 to 14 can be analyzed. The analysis understands Java 14 standard language features. + .. [5] ECJ is supported when the build invokes it via the Maven Compiler plugin or the Takari Lifecycle plugin. + .. [6] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files. + .. [7] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default for LGTM. diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv deleted file mode 100644 index 343de95dfba..00000000000 --- a/docs/language/support/versions-compilers.csv +++ /dev/null @@ -1,18 +0,0 @@ -Language,Variants,Compilers,Extensions -C/C++,"C89, C99, C11, C18, C++98, C++03, C++11, C++14, C++17","Clang (and clang-cl [1]_) extensions (up to Clang 9.0), - -GNU extensions (up to GCC 9.2), - -Microsoft extensions (up to VS 2019), - -Arm Compiler 5 [2]_","``.cpp``, ``.c++``, ``.cxx``, ``.hpp``, ``.hh``, ``.h++``, ``.hxx``, ``.c``, ``.cc``, ``.h``" -C#,C# up to 8.0. with .NET up to 4.8 [3]_,"Microsoft Visual Studio up to 2019, - -.NET Core up to 3.0","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" -Go (aka Golang), "Go up to 1.13", "Go 1.11 or more recent", ``.go`` -Java,"Java 6 to 13 [4]_","javac (OpenJDK and Oracle JDK), - -Eclipse compiler for Java (ECJ) [5]_",``.java`` -JavaScript,ECMAScript 2019 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhm``, ``.xhtml``, ``.vue``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [6]_" -Python,"2.7, 3.5, 3.6, 3.7, 3.8",Not applicable,``.py`` -TypeScript [7]_,"2.6-3.7",Standard TypeScript compiler,"``.ts``, ``.tsx``" diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md index 58e2d93f95e..147e18d5aac 100644 --- a/docs/query-help-style-guide.md +++ b/docs/query-help-style-guide.md @@ -2,7 +2,7 @@ ## Introduction -When you contribute a new query to Semmle/ql for inclusion in the standard queries, or add a custom query for analysis in LGTM, you should also write a query help file. This file provides detailed information about the purpose and use of the query, which is available to users in LGTM (for example [here](https://lgtm.com/rules/1506093386171/)) and on the query homepages: +When you contribute a new [supported query](supported-queries.md) to this repository, or add a custom query for analysis in LGTM, you should also write a query help file. This file provides detailed information about the purpose and use of the query, which is available to users in LGTM (for example [here](https://lgtm.com/rules/1506093386171/)) and on the query homepages: * [C/C++ queries](https://help.semmle.com/wiki/display/CCPPOBJ/) * [C# queries](https://help.semmle.com/wiki/display/CSHARP/) @@ -16,7 +16,7 @@ Query help files must have the same base name as the query they describe and mus ### File structure and layout -Query files are written using an XML format called Qhelp, and stored in a file with a `.qhelp` extension. The basic structure is as follows: +Query help files are written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows: ``` @@ -25,7 +25,7 @@ Query files are written using an XML format called Qhelp, and stored in a file w ``` -The header and single top-level `qhelp` element are both mandatory. +The header and single top-level `` element are both mandatory. ### Section-level elements @@ -36,7 +36,7 @@ Section-level elements are used to group the information within the query help f 3. `example`—an example of code showing the problem. Where possible, this section should also include a solution to the issue. 4. `references`—relevant references, such as authoritative sources on language semantics and best practice. -For further information about the other section-level, block, list and table elements supported by the qhelp format, see the [Query help reference](https://help.semmle.com/QL/learn-ql/ql/writing-queries/query-help.html) on help.semmle.com. +For further information about the other section-level, block, list and table elements supported by query help files, see the [Query help reference](https://help.semmle.com/QL/learn-ql/ql/writing-queries/query-help.html) on help.semmle.com. ## English style @@ -86,7 +86,7 @@ For example: >W. C. Wake, _Refactoring Workbook_, pp. 93 – 94, Addison-Wesley Professional, 2004. -Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the html files generated from the qhelp files. +Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the HTML files generated from the query help files. ### Academic papers @@ -107,11 +107,11 @@ For example: ### Referencing potential security weaknesses -If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the qhelp file. +If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the output HTML file. ## Query help example -The following example is a qhelp file for a query from the standard query suite for Java: +The following example is a query help file for a query from the standard query suite for Java: ``` -``` \ No newline at end of file +``` diff --git a/java/ql/src/codeql-suites/java-code-scanning.qls b/java/ql/src/codeql-suites/java-code-scanning.qls new file mode 100644 index 00000000000..7dc29ab8049 --- /dev/null +++ b/java/ql/src/codeql-suites/java-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for Java +- qlpack: codeql-java +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/java/ql/src/config/semmlecode.dbscheme b/java/ql/src/config/semmlecode.dbscheme index 054d7e823b2..2a682863863 100755 --- a/java/ql/src/config/semmlecode.dbscheme +++ b/java/ql/src/config/semmlecode.dbscheme @@ -268,6 +268,10 @@ classes( int sourceid: @class ref ); +isRecord( + unique int id: @class ref +); + interfaces( unique int id: @interface, string nodeName: string ref, diff --git a/java/ql/src/config/semmlecode.dbscheme.stats b/java/ql/src/config/semmlecode.dbscheme.stats index 165db4674b5..ae0f5e3b34f 100644 --- a/java/ql/src/config/semmlecode.dbscheme.stats +++ b/java/ql/src/config/semmlecode.dbscheme.stats @@ -9263,6 +9263,17 @@ +isRecord +100 + + +id +100 + + + + + interfaces 249736 diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.java b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.java new file mode 100644 index 00000000000..d0772b8cdbd --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.java @@ -0,0 +1,8 @@ +public class TestServlet extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + // BAD: a URL from a remote source is opened with URL#openStream() + URL url = new URL(request.getParameter("url")); + InputStream inputStream = new URL(url).openStream(); + } +} diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp new file mode 100644 index 00000000000..dc4c3c161c4 --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.qhelp @@ -0,0 +1,33 @@ + + + + +

Calling openStream on URLs created from remote source can lead to local file disclosure.

+

If openStream is called on a java.net.URL, that was created from a remote source, +an attacker can try to pass absolute URLs starting with file:// or jar:// to access +local resources in addition to remote ones.

+
+ + +

When you construct a URL using java.net.URL from a remote source, +don't call openStream on it. Instead, use an HTTP Client to fetch the URL and access its content. +You should also validate the URL to check that it uses the correct protocol and host combination.

+
+ + +

The following example shows an URL that is constructed from a request parameter. Afterwards openStream +is called on the URL, potentially leading to a local file access.

+ +
+ + +
  • Java Platform, Standard Edition 11, API Specification: + +Class URL. +
  • + + + + diff --git a/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql new file mode 100644 index 00000000000..ab315277f2b --- /dev/null +++ b/java/ql/src/experimental/Security/CWE/CWE-036/OpenStream.ql @@ -0,0 +1,55 @@ +/** + * @name openStream called on URLs created from remote source + * @description Calling openStream on URLs created from remote source + * can lead to local file disclosure. + * @kind path-problem + */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +import DataFlow::PathGraph + +class URLConstructor extends ClassInstanceExpr { + URLConstructor() { this.getConstructor().getDeclaringType() instanceof TypeUrl } + + Expr stringArg() { + // Query only in URL's that were constructed by calling the single parameter string constructor. + this.getConstructor().getNumberOfParameters() = 1 and + this.getConstructor().getParameter(0).getType() instanceof TypeString and + result = this.getArgument(0) + } +} + +class URLOpenStreamMethod extends Method { + URLOpenStreamMethod() { + this.getDeclaringType() instanceof TypeUrl and + this.getName() = "openStream" + } +} + +class RemoteURLToOpenStreamFlowConfig extends TaintTracking::Configuration { + RemoteURLToOpenStreamFlowConfig() { this = "OpenStream::RemoteURLToOpenStreamFlowConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { + exists(MethodAccess m | + sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenStreamMethod + ) + } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + exists(URLConstructor u | + node1.asExpr() = u.stringArg() and + node2.asExpr() = u + ) + } +} + +from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess call +where + sink.getNode().asExpr() = call.getQualifier() and + any(RemoteURLToOpenStreamFlowConfig c).hasFlowPath(source, sink) +select call, source, sink, + "URL on which openStream is called may have been constructed from remote source" diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index f8b703f9440..7c48700e295 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-java version: 0.0.0 dbscheme: config/semmlecode.dbscheme suites: codeql-suites +extractor: java diff --git a/java/ql/src/semmle/code/java/Expr.qll b/java/ql/src/semmle/code/java/Expr.qll index 37cc608d878..73475f6cc70 100755 --- a/java/ql/src/semmle/code/java/Expr.qll +++ b/java/ql/src/semmle/code/java/Expr.qll @@ -1076,8 +1076,6 @@ class ConditionalExpr extends Expr, @conditionalexpr { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * A `switch` expression. */ class SwitchExpr extends Expr, @switchexpr { @@ -1132,7 +1130,25 @@ deprecated class ParExpr extends Expr, @parexpr { /** An `instanceof` expression. */ class InstanceOfExpr extends Expr, @instanceofexpr { /** Gets the expression on the left-hand side of the `instanceof` operator. */ - Expr getExpr() { result.isNthChildOf(this, 0) } + Expr getExpr() { + if isPattern() + then result = getLocalVariableDeclExpr().getInit() + else result.isNthChildOf(this, 0) + } + + /** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * Holds if this `instanceof` expression uses pattern matching. + */ + predicate isPattern() { exists(getLocalVariableDeclExpr()) } + + /** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * Gets the local variable declaration of this `instanceof` expression if pattern matching is used. + */ + LocalVariableDeclExpr getLocalVariableDeclExpr() { result.isNthChildOf(this, 0) } /** Gets the access to the type on the right-hand side of the `instanceof` operator. */ Expr getTypeName() { result.isNthChildOf(this, 1) } @@ -1163,6 +1179,8 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr { exists(ForStmt fs | fs.getAnInit() = this | result.isNthChildOf(fs, 0)) or exists(EnhancedForStmt efs | efs.getVariable() = this | result.isNthChildOf(efs, -1)) + or + exists(InstanceOfExpr ioe | this.getParent() = ioe | result.isNthChildOf(ioe, 1)) } /** Gets the name of the variable declared by this local variable declaration expression. */ diff --git a/java/ql/src/semmle/code/java/Statement.qll b/java/ql/src/semmle/code/java/Statement.qll index 2a5f94ef781..fa303a7c3ee 100755 --- a/java/ql/src/semmle/code/java/Statement.qll +++ b/java/ql/src/semmle/code/java/Statement.qll @@ -417,8 +417,6 @@ class SwitchCase extends Stmt, @case { SwitchStmt getSwitch() { result.getACase() = this } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the switch expression to which this case belongs, if any. */ SwitchExpr getSwitchExpr() { result.getACase() = this } @@ -432,8 +430,6 @@ class SwitchCase extends Stmt, @case { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Holds if this `case` is a switch labeled rule of the form `... -> ...`. */ predicate isRule() { @@ -443,15 +439,11 @@ class SwitchCase extends Stmt, @case { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the expression on the right-hand side of the arrow, if any. */ Expr getRuleExpression() { result.getParent() = this and result.getIndex() = -1 } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the statement on the right-hand side of the arrow, if any. */ Stmt getRuleStatement() { result.getParent() = this and result.getIndex() = -1 } @@ -465,8 +457,6 @@ class ConstCase extends SwitchCase { Expr getValue() { result.getParent() = this and result.getIndex() = 0 } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * Gets the `case` constant at the specified index. */ Expr getValue(int i) { result.getParent() = this and result.getIndex() = i and i >= 0 } @@ -624,8 +614,6 @@ class BreakStmt extends Stmt, @breakstmt { } /** - * PREVIEW FEATURE in Java 13. Subject to removal in a future release. - * * A `yield` statement. */ class YieldStmt extends Stmt, @yieldstmt { diff --git a/java/ql/src/semmle/code/java/Type.qll b/java/ql/src/semmle/code/java/Type.qll index f08c5a5eea4..35f35d44928 100755 --- a/java/ql/src/semmle/code/java/Type.qll +++ b/java/ql/src/semmle/code/java/Type.qll @@ -615,6 +615,15 @@ class Class extends RefType, @class { } } +/** + * PREVIEW FEATURE in Java 14. Subject to removal in a future release. + * + * A record declaration. + */ +class Record extends Class { + Record() { isRecord(this) } +} + /** An intersection type. */ class IntersectionType extends RefType, @class { IntersectionType() { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 7d2d728b67e..a1daeb66411 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 7d2d728b67e..a1daeb66411 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 7d2d728b67e..a1daeb66411 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 7d2d728b67e..a1daeb66411 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 7d2d728b67e..a1daeb66411 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -2089,6 +2089,8 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { SummaryCtxSome() { this = TSummaryCtxSome(p, ap) } + int getParameterPos() { p.isParameterOf(_, result) } + override string toString() { result = p + ": " + ap } predicate hasLocationInfo( @@ -2482,13 +2484,15 @@ pragma[nomagic] private predicate paramFlowsThrough( ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, Configuration config ) { - exists(PathNodeMid mid, ReturnNodeExt ret | + exists(PathNodeMid mid, ReturnNodeExt ret, int pos | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and sc = mid.getSummaryCtx() and config = mid.getConfiguration() and - ap = mid.getAp() + ap = mid.getAp() and + pos = sc.getParameterPos() and + not kind.(ParamUpdateReturnKind).getPosition() = pos ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll new file mode 100644 index 00000000000..0dc3b8eff45 --- /dev/null +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -0,0 +1,175 @@ +/** + * Provides consistency queries for checking invariants in the language-specific + * data-flow classes and predicates. + */ + +private import DataFlowImplSpecific::Private +private import DataFlowImplSpecific::Public +private import tainttracking1.TaintTrackingParameter::Private +private import tainttracking1.TaintTrackingParameter::Public + +module Consistency { + private class RelevantNode extends Node { + RelevantNode() { + this instanceof ArgumentNode or + this instanceof ParameterNode or + this instanceof ReturnNode or + this = getAnOutNode(_, _) or + simpleLocalFlowStep(this, _) or + simpleLocalFlowStep(_, this) or + jumpStep(this, _) or + jumpStep(_, this) or + storeStep(this, _, _) or + storeStep(_, _, this) or + readStep(this, _, _) or + readStep(_, _, this) or + defaultAdditionalTaintStep(this, _) or + defaultAdditionalTaintStep(_, this) + } + } + + query predicate uniqueEnclosingCallable(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getEnclosingCallable()) and + c != 1 and + msg = "Node should have one enclosing callable but has " + c + "." + ) + } + + query predicate uniqueTypeBound(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(n.getTypeBound()) and + c != 1 and + msg = "Node should have one type bound but has " + c + "." + ) + } + + query predicate uniqueTypeRepr(Node n, string msg) { + exists(int c | + n instanceof RelevantNode and + c = count(getErasedRepr(n.getTypeBound())) and + c != 1 and + msg = "Node should have one type representation but has " + c + "." + ) + } + + query predicate uniqueNodeLocation(Node n, string msg) { + exists(int c | + c = + count(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) and + c != 1 and + msg = "Node should have one location but has " + c + "." + ) + } + + query predicate missingLocation(string msg) { + exists(int c | + c = + strictcount(Node n | + not exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | + n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + ) + ) and + msg = "Nodes without location: " + c + ) + } + + query predicate uniqueNodeToString(Node n, string msg) { + exists(int c | + c = count(n.toString()) and + c != 1 and + msg = "Node should have one toString but has " + c + "." + ) + } + + query predicate missingToString(string msg) { + exists(int c | + c = strictcount(Node n | not exists(n.toString())) and + msg = "Nodes without toString: " + c + ) + } + + query predicate parameterCallable(ParameterNode p, string msg) { + exists(DataFlowCallable c | p.isParameterOf(c, _) and c != p.getEnclosingCallable()) and + msg = "Callable mismatch for parameter." + } + + query predicate localFlowIsLocal(Node n1, Node n2, string msg) { + simpleLocalFlowStep(n1, n2) and + n1.getEnclosingCallable() != n2.getEnclosingCallable() and + msg = "Local flow step does not preserve enclosing callable." + } + + private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) } + + query predicate compatibleTypesReflexive(DataFlowType t, string msg) { + t = typeRepr() and + not compatibleTypes(t, t) and + msg = "Type compatibility predicate is not reflexive." + } + + query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { + isUnreachableInCall(n, call) and + exists(DataFlowCallable c | + c = n.getEnclosingCallable() and + not viableCallable(call) = c + ) and + msg = "Call context for isUnreachableInCall is inconsistent with call graph." + } + + query predicate localCallNodes(DataFlowCall call, Node n, string msg) { + ( + n = getAnOutNode(call, _) and + msg = "OutNode and call does not share enclosing callable." + or + n.(ArgumentNode).argumentOf(call, _) and + msg = "ArgumentNode and call does not share enclosing callable." + ) and + n.getEnclosingCallable() != call.getEnclosingCallable() + } + + query predicate postIsNotPre(PostUpdateNode n, string msg) { + n.getPreUpdateNode() = n and msg = "PostUpdateNode should not equal its pre-update node." + } + + query predicate postHasUniquePre(PostUpdateNode n, string msg) { + exists(int c | + c = count(n.getPreUpdateNode()) and + c != 1 and + msg = "PostUpdateNode should have one pre-update node but has " + c + "." + ) + } + + query predicate uniquePostUpdate(Node n, string msg) { + 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and + msg = "Node has multiple PostUpdateNodes." + } + + query predicate postIsInSameCallable(PostUpdateNode n, string msg) { + n.getEnclosingCallable() != n.getPreUpdateNode().getEnclosingCallable() and + msg = "PostUpdateNode does not share callable with its pre-update node." + } + + private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } + + query predicate reverseRead(Node n, string msg) { + exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and + msg = "Origin of readStep is missing a PostUpdateNode." + } + + query predicate storeIsPostUpdate(Node n, string msg) { + storeStep(_, _, n) and + not n instanceof PostUpdateNode and + msg = "Store targets should be PostUpdateNodes." + } + + query predicate argHasPostUpdate(ArgumentNode n, string msg) { + not hasPost(n) and + not isImmutableOrUnobservable(n) and + msg = "ArgumentNode is missing PostUpdateNode." + } +} diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index e60f49ffa6a..90f443e5578 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -327,3 +327,14 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) { } int accessPathLimit() { result = 5 } + +/** + * Holds if `n` does not require a `PostUpdateNode` as it either cannot be + * modified or its modification cannot be observed, for example if it is a + * freshly created object that is not saved in a variable. + * + * This predicate is only used for consistency checks. + */ +predicate isImmutableOrUnobservable(Node n) { + n.getType() instanceof ImmutableType or n instanceof ImplicitVarargsArray +} diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll index 4eb9b51a74a..74b492f76bb 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -11,7 +11,10 @@ import semmle.code.java.dataflow.InstanceAccess cached private newtype TNode = - TExprNode(Expr e) or + TExprNode(Expr e) { + not e.getType() instanceof VoidType and + not e.getParent*() instanceof Annotation + } or TExplicitParameterNode(Parameter p) { exists(p.getCallable().getBody()) } or TImplicitVarargsArray(Call c) { c.getCallee().isVarargs() and diff --git a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll index c05de75bfab..e8b828f5b3e 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll @@ -1,3 +1,13 @@ +/** + * Provides an implementation of global (interprocedural) taint tracking. + * This file re-exports the local (intraprocedural) taint-tracking analysis + * from `TaintTrackingParameter::Public` and adds a global analysis, mainly + * exposed through the `Configuration` class. For some languages, this file + * exists in several identical copies, allowing queries to use multiple + * `Configuration` classes that depend on each other without introducing + * mutual recursion among those configurations. + */ + import TaintTrackingParameter::Public private import TaintTrackingParameter::Private diff --git a/java/ql/src/semmle/code/java/frameworks/Networking.qll b/java/ql/src/semmle/code/java/frameworks/Networking.qll index 3889c5a8b5d..92575995636 100644 --- a/java/ql/src/semmle/code/java/frameworks/Networking.qll +++ b/java/ql/src/semmle/code/java/frameworks/Networking.qll @@ -12,6 +12,10 @@ class TypeSocket extends RefType { TypeSocket() { hasQualifiedName("java.net", "Socket") } } +class TypeUrl extends RefType { + TypeUrl() { hasQualifiedName("java.net", "URL") } +} + class URLConnectionGetInputStreamMethod extends Method { URLConnectionGetInputStreamMethod() { getDeclaringType() instanceof TypeUrlConnection and diff --git a/java/ql/test/library-tests/guards12/options b/java/ql/test/library-tests/guards12/options index 99827347b32..3f12170222c 100644 --- a/java/ql/test/library-tests/guards12/options +++ b/java/ql/test/library-tests/guards12/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args --enable-preview -source 13 -target 13 +//semmle-extractor-options: --javac-args -source 14 -target 14 diff --git a/java/ql/test/library-tests/structure/DeclaresMember.expected b/java/ql/test/library-tests/structure/DeclaresMember.expected index f4a9c678cc3..32c5f05891b 100644 --- a/java/ql/test/library-tests/structure/DeclaresMember.expected +++ b/java/ql/test/library-tests/structure/DeclaresMember.expected @@ -28,7 +28,6 @@ | LocalClass | LocalClass | | LocalClass | n | | MemberClass | MemberClass | -| Object | | | Object | Object | | Object | clone | | Object | equals | diff --git a/java/ql/test/qlpack.yml b/java/ql/test/qlpack.yml index d4b46d7d2b0..75a27d69080 100644 --- a/java/ql/test/qlpack.yml +++ b/java/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-java-tests version: 0.0.0 libraryPathDependencies: codeql-java +extractor: java diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme new file mode 100755 index 00000000000..054d7e823b2 --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/old.dbscheme @@ -0,0 +1,950 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @class ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme new file mode 100755 index 00000000000..2a682863863 --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/semmlecode.dbscheme @@ -0,0 +1,954 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/* + * Locations and files + */ + +@location = @location_default ; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref // deprecated +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +classes( + unique int id: @class, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @class ref +); + +isRecord( + unique int id: @class ref +); + +interfaces( + unique int id: @interface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @interface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @interface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @class ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @typeorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @typeorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @class ref, + int parent: @classinstancexpr ref +); + +#keyset[classid] #keyset[parent] +isLocalClass( + int classid: @class ref, + int parent: @localclassdeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @interface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @typeorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localclassdeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +; + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +@exprparent = @stmt | @expr | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@typeorpackage = @type | @package; + +@typeorcallable = @type | @callable; +@classorinterface = @interface | @class; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype; +@classorarray = @class | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; +@element = @file | @package | @primitive | @class | @interface | @method | @constructor | @modifier | @param | @exception | @field | + @annotation | @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl; + +@modifiable = @member_modifiable| @param | @localvar ; + +@member_modifiable = @class | @interface | @method | @constructor | @field ; + +@member = @method | @constructor | @field | @reftype ; + +@locatable = @file | @class | @interface | @fielddecl | @field | @constructor | @method | @param | @exception + | @boundedtype | @typebound | @array | @primitive + | @import | @stmt | @expr | @localvar | @javadoc | @javadocTag | @javadocText + | @xmllocatable; + +@top = @element | @locatable | @folder; + +/* + * XML Files + */ + +xmlEncoding( + unique int id: @file ref, + string encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; diff --git a/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties new file mode 100644 index 00000000000..d42c96673ad --- /dev/null +++ b/java/upgrades/054d7e823b2c5b93bf2a14d5c22a107934fbc133/upgrade.properties @@ -0,0 +1,2 @@ +description: Java 14: add `isRecord` relation +compatibility: backwards diff --git a/javascript/documentation/flow-summaries.rst b/javascript/documentation/flow-summaries.rst index edd6cb027b0..6a6c482f69d 100644 --- a/javascript/documentation/flow-summaries.rst +++ b/javascript/documentation/flow-summaries.rst @@ -5,7 +5,7 @@ Overview -------- This document presents an approach for running information flow analyses (such as the standard -Semmle security queries) on an application that depends on one or more npm packages. Instead of +security queries) on an application that depends on one or more npm packages. Instead of installing the npm packages during the snapshot build and analyzing them together with application code, we analyze each package in isolation and compute *flow summaries* that record information about any sources, sinks and flow steps contributed by the package's API. These flow summaries @@ -41,7 +41,7 @@ If the value of ``p`` can be controlled by an untrusted user, this would allow t folders, which may not be desirable. By analyzing the application code base together with the source code for the ``mkdirp`` package, -Semmle's default path injection analysis would be able to track taint through the call to ``mkdirp`` into its +the default path injection analysis would be able to track taint through the call to ``mkdirp`` into its implementation, which ultimately uses built-in Node.js file system APIs to create the folder. Since the path injection analysis has built-in models of these APIs it would then be able to spot and flag this vulnerability. diff --git a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java index f750013067b..6ad5cca137e 100644 --- a/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/ESNextParser.java @@ -482,6 +482,7 @@ public class ESNextParser extends JSXParser { if (code == '_') { if (underscoreAllowed) { + seenUnderscoreNumericSeparator = true; // no adjacent underscores underscoreAllowed = false; ++this.pos; diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index eee2e172a6d..a8348c3c307 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -145,6 +145,11 @@ public class Parser { private Stack labels; protected int yieldPos, awaitPos; + /** + * Set to true by {@link ESNextParser#readInt} if the parsed integer contains an underscore. + */ + protected boolean seenUnderscoreNumericSeparator = false; + /** * For readability purposes, we pass this instead of false as the argument to the * hasDeclareKeyword parameter (which only exists in TypeScript). @@ -654,7 +659,7 @@ public class Parser { case 58: ++this.pos; return this.finishToken(TokenType.colon); - case 35: + case 35: ++this.pos; return this.finishToken(TokenType.pound); case 63: @@ -847,6 +852,10 @@ public class Parser { } String str = inputSubstring(start, this.pos); + if (seenUnderscoreNumericSeparator) { + str = str.replace("_", ""); + seenUnderscoreNumericSeparator = false; + } Number val = null; if (isFloat) val = parseFloat(str); else if (!octal || str.length() == 1) val = parseInt(str, 10); diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 35295ae0678..36f831720f4 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -565,17 +565,40 @@ public class AutoBuild { extractTypeScript( defaultExtractor, filesToExtract, tsconfigFiles, dependencyInstallationResult); + boolean hasTypeScriptFiles = extractedFiles.size() > 0; + // extract remaining files for (Path f : filesToExtract) { - if (extractedFiles.add(f)) { - FileExtractor extractor = defaultExtractor; - if (!fileTypes.isEmpty()) { - String extension = FileUtil.extension(f); - if (customExtractors.containsKey(extension)) extractor = customExtractors.get(extension); - } - extract(extractor, f, null); + if (extractedFiles.contains(f)) + continue; + if (hasTypeScriptFiles && isFileDerivedFromTypeScriptFile(f, extractedFiles)) { + continue; + } + extractedFiles.add(f); + FileExtractor extractor = defaultExtractor; + if (!fileTypes.isEmpty()) { + String extension = FileUtil.extension(f); + if (customExtractors.containsKey(extension)) extractor = customExtractors.get(extension); + } + extract(extractor, f, null); + } + } + + /** + * Returns true if the given path is likely the output of compiling a TypeScript file + * which we have already extracted. + */ + private boolean isFileDerivedFromTypeScriptFile(Path path, Set extractedFiles) { + String name = path.getFileName().toString(); + if (!name.endsWith(".js")) + return false; + String stem = name.substring(0, name.length() - ".js".length()); + for (String ext : FileType.TYPESCRIPT.getExtensions()) { + if (extractedFiles.contains(path.getParent().resolve(stem + ext))) { + return true; } } + return false; } /** Returns true if yarn is installed, otherwise prints a warning and returns false. */ @@ -613,7 +636,7 @@ public class AutoBuild { } return null; } - + /** * Returns an existing file named dir/stem.ext where ext is any TypeScript or JavaScript extension, * or null if no such file exists. @@ -623,7 +646,7 @@ public class AutoBuild { if (resolved != null) return resolved; return tryResolveWithExtensions(dir, stem, FileType.JS.getExtensions()); } - + /** * Gets a child of a JSON object as a string, or null. */ @@ -658,7 +681,7 @@ public class AutoBuild { if (!verifyYarnInstallation()) { return DependencyInstallationResult.empty; } - + final Path sourceRoot = Paths.get(".").toAbsolutePath(); final Path virtualSourceRoot = Paths.get(EnvironmentVariables.getScratchDir()).toAbsolutePath(); @@ -746,7 +769,7 @@ public class AutoBuild { for (Path file : packageJsonFiles.keySet()) { Path relativePath = sourceRoot.relativize(file); Path virtualFile = virtualSourceRoot.resolve(relativePath); - + try { Files.createDirectories(virtualFile.getParent()); try (Writer writer = Files.newBufferedWriter(virtualFile)) { @@ -794,7 +817,7 @@ public class AutoBuild { */ private Path guessPackageMainFile(Path packageJsonFile, JsonObject packageJson, Iterable extensions) { Path packageDir = packageJsonFile.getParent(); - + // Try /index.ts. Path resolved = tryResolveWithExtensions(packageDir, "index", extensions); if (resolved != null) { diff --git a/javascript/extractor/src/com/semmle/js/extractor/Main.java b/javascript/extractor/src/com/semmle/js/extractor/Main.java index 81e25eb23e0..904969a168f 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/Main.java +++ b/javascript/extractor/src/com/semmle/js/extractor/Main.java @@ -1,5 +1,13 @@ package com.semmle.js.extractor; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + import com.semmle.js.extractor.ExtractorConfig.HTMLHandling; import com.semmle.js.extractor.ExtractorConfig.Platform; import com.semmle.js.extractor.ExtractorConfig.SourceType; @@ -23,13 +31,6 @@ import com.semmle.util.language.LegacyLanguage; import com.semmle.util.process.ArgsParser; import com.semmle.util.process.ArgsParser.FileMode; import com.semmle.util.trap.TrapWriter; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; /** The main entry point of the JavaScript extractor. */ public class Main { @@ -37,7 +38,7 @@ public class Main { * A version identifier that should be updated every time the extractor changes in such a way that * it may produce different tuples for the same file under the same {@link ExtractorConfig}. */ - public static final String EXTRACTOR_VERSION = "2020-02-14"; + public static final String EXTRACTOR_VERSION = "2020-04-01"; public static final Pattern NEWLINE = Pattern.compile("\n"); @@ -190,10 +191,29 @@ public class Main { // Extract files that were not part of a project. for (File f : files) { + if (isFileDerivedFromTypeScriptFile(f)) + continue; ensureFileIsExtracted(f, ap); } } + /** + * Returns true if the given path is likely the output of compiling a TypeScript file + * which we have already extracted. + */ + private boolean isFileDerivedFromTypeScriptFile(File path) { + String name = path.getName(); + if (!name.endsWith(".js")) + return false; + String stem = name.substring(0, name.length() - ".js".length()); + for (String ext : FileType.TYPESCRIPT.getExtensions()) { + if (new File(path.getParent(), stem + ext).exists()) { + return true; + } + } + return false; + } + private void extractTypeTable(File fileHandle, TypeTable table) { TrapWriter trapWriter = extractorOutputConfig diff --git a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql index 8fcd88724af..1002ac0a4e3 100644 --- a/javascript/ql/src/Declarations/DeadStoreOfLocal.ql +++ b/javascript/ql/src/Declarations/DeadStoreOfLocal.ql @@ -63,8 +63,10 @@ where ( // To avoid confusion about the meaning of "definition" and "declaration" we avoid // the term "definition" when the alert location is a variable declaration. - if dead instanceof VariableDeclarator + if + dead instanceof VariableDeclarator and + not exists(SsaImplicitInit init | init.getVariable().getSourceVariable() = v) // the variable is dead at the hoisted implicit initialization. then msg = "The initial value of " + v.getName() + " is unused, since it is always overwritten." - else msg = "This definition of " + v.getName() + " is useless, since its value is never read." + else msg = "The value assigned to " + v.getName() + " here is unused." ) select dead, msg diff --git a/javascript/ql/src/Expressions/MissingAwait.ql b/javascript/ql/src/Expressions/MissingAwait.ql index be40eef0d4b..e4c092af5c9 100644 --- a/javascript/ql/src/Expressions/MissingAwait.ql +++ b/javascript/ql/src/Expressions/MissingAwait.ql @@ -45,7 +45,8 @@ predicate isBadPromiseContext(Expr expr) { or exists(UnaryExpr e | expr = e.getOperand() and - not e instanceof VoidExpr + not e instanceof VoidExpr and + not e instanceof DeleteExpr ) or expr = any(UpdateExpr e).getOperand() diff --git a/javascript/ql/src/Expressions/MisspelledVariableName.ql b/javascript/ql/src/Expressions/MisspelledVariableName.ql index ce5dc546341..b6f0ad88e3e 100644 --- a/javascript/ql/src/Expressions/MisspelledVariableName.ql +++ b/javascript/ql/src/Expressions/MisspelledVariableName.ql @@ -14,6 +14,37 @@ import Misspelling -from GlobalVarAccess gva, VarDecl lvd -where misspelledVariableName(gva, lvd) -select gva, "'" + gva + "' may be a typo for variable $@.", lvd, lvd.getName() +/** + * Gets the number of times a local variable with name `name` occurs in the program. + */ +bindingset[name] +int localAcceses(string name) { + result = count(VarAccess acc | acc.getName() = name and not acc instanceof GlobalVarAccess) +} + +/** + * Gets the number of times a global variable with name `name` occurs in the program. + */ +bindingset[name] +int globalAccesses(string name) { result = count(GlobalVarAccess acc | acc.getName() = name) } + +/** + * Holds if our heuristic says that the local variable `lvd` seems to be a misspelling of the global variable `gva`. + * Otherwise the global variable is likely the misspelling. + */ +predicate globalIsLikelyCorrect(GlobalVarAccess gva, VarDecl lvd) { + // If there are more occurrences of the global (by a margin of at least 2), and the local is missing one letter compared to the global. + globalAccesses(gva.getName()) >= localAcceses(lvd.getName()) + 2 and + lvd.getName().length() = gva.getName().length() - 1 + or + // Or if there are many more of the global. + globalAccesses(gva.getName()) > 2 * localAcceses(lvd.getName()) + 2 +} + +from GlobalVarAccess gva, VarDecl lvd, string msg +where + misspelledVariableName(gva, lvd) and + if globalIsLikelyCorrect(gva, lvd) + then msg = "$@ may be a typo for '" + gva + "'." + else msg = "'" + gva + "' may be a typo for variable $@." +select gva, msg, lvd, lvd.getName() diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql index 86ab1744086..0a9314382f2 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql @@ -12,11 +12,46 @@ */ import javascript -import semmle.javascript.dataflow.internal.AccessPaths /** A URL scheme that can be used to represent executable code. */ class DangerousScheme extends string { DangerousScheme() { this = "data:" or this = "javascript:" or this = "vbscript:" } + + /** Gets the name of this scheme without the `:`. */ + string getWithoutColon() { this = result + ":" } + + /** Gets the name of this scheme, with or without the `:`. */ + string getWithOrWithoutColon() { result = this or result = getWithoutColon() } +} + +/** Returns a node that refers to the scheme of `url`. */ +DataFlow::SourceNode schemeOf(DataFlow::Node url) { + // url.split(":")[0] + exists(DataFlow::MethodCallNode split | + split.getMethodName() = "split" and + split.getArgument(0).getStringValue() = ":" and + result = split.getAPropertyRead("0") and + url = split.getReceiver() + ) + or + // url.getScheme(), url.getProtocol(), getScheme(url), getProtocol(url) + exists(DataFlow::CallNode call | + result = call and + (call.getCalleeName() = "getScheme" or call.getCalleeName() = "getProtocol") + | + call.getNumArgument() = 1 and + url = call.getArgument(0) + or + call.getNumArgument() = 0 and + url = call.getReceiver() + ) + or + // url.scheme, url.protocol + exists(DataFlow::PropRead prop | + result = prop and + (prop.getPropertyName() = "scheme" or prop.getPropertyName() = "protocol") and + url = prop.getBase() + ) } /** Gets a data-flow node that checks `nd` against the given `scheme`. */ @@ -27,6 +62,20 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) { sw.getSubstring().mayHaveStringValue(scheme) ) or + // check of the form `array.includes(getScheme(nd))` + exists(InclusionTest test, DataFlow::ArrayCreationNode array | test = result | + schemeOf(nd).flowsTo(test.getContainedNode()) and + array.flowsTo(test.getContainerNode()) and + array.getAnElement().mayHaveStringValue(scheme.getWithOrWithoutColon()) + ) + or + // check of the form `getScheme(nd) === scheme` + exists(EqualityTest test, Expr op1, Expr op2 | test.flow() = result | + test.hasOperands(op1, op2) and + schemeOf(nd).flowsToExpr(op1) and + op2.mayHaveStringValue(scheme.getWithOrWithoutColon()) + ) + or // propagate through trimming, case conversion, and regexp replace exists(DataFlow::MethodCallNode stringop | stringop.getMethodName().matches("trim%") or @@ -42,14 +91,14 @@ DataFlow::Node schemeCheck(DataFlow::Node nd, DangerousScheme scheme) { } /** Gets a data-flow node that checks an instance of `ap` against the given `scheme`. */ -DataFlow::Node schemeCheckOn(AccessPath ap, DangerousScheme scheme) { - result = schemeCheck(ap.getAnInstance().flow(), scheme) +DataFlow::Node schemeCheckOn(DataFlow::SourceNode root, string path, DangerousScheme scheme) { + result = schemeCheck(AccessPath::getAReferenceTo(root, path), scheme) } -from AccessPath ap, int n +from DataFlow::SourceNode root, string path, int n where n = strictcount(DangerousScheme s) and - strictcount(DangerousScheme s | exists(schemeCheckOn(ap, s))) < n -select schemeCheckOn(ap, "javascript:"), + strictcount(DangerousScheme s | exists(schemeCheckOn(root, path, s))) < n +select schemeCheckOn(root, path, "javascript:"), "This check does not consider " + - strictconcat(DangerousScheme s | not exists(schemeCheckOn(ap, s)) | s, " and ") + "." + strictconcat(DangerousScheme s | not exists(schemeCheckOn(root, path, s)) | s, " and ") + "." diff --git a/javascript/ql/src/codeql-suites/javascript-code-scanning.qls b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls new file mode 100644 index 00000000000..f87a55157a2 --- /dev/null +++ b/javascript/ql/src/codeql-suites/javascript-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for JavaScript +- qlpack: codeql-javascript +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/javascript/ql/src/qlpack.yml b/javascript/ql/src/qlpack.yml index 1f587affc85..7612a1d52f2 100644 --- a/javascript/ql/src/qlpack.yml +++ b/javascript/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-javascript version: 0.0.0 dbscheme: semmlecode.javascript.dbscheme suites: codeql-suites +extractor: javascript diff --git a/javascript/ql/src/semmle/javascript/AMD.qll b/javascript/ql/src/semmle/javascript/AMD.qll index 38d049c088d..799db5e0fb5 100644 --- a/javascript/ql/src/semmle/javascript/AMD.qll +++ b/javascript/ql/src/semmle/javascript/AMD.qll @@ -56,10 +56,16 @@ class AmdModuleDefinition extends CallExpr { */ pragma[nomagic] DataFlow::SourceNode getFactoryNode() { - result.flowsToExpr(getLastArgument()) and + result = getFactoryNodeInternal() and result instanceof DataFlow::ValueNode } + private DataFlow::Node getFactoryNodeInternal() { + // To avoid recursion, this should not depend on `SourceNode`. + result = DataFlow::valueNode(getLastArgument()) or + result = getFactoryNodeInternal().getAPredecessor() + } + /** Gets the expression defining this module. */ Expr getModuleExpr() { exists(DataFlow::Node f | f = getFactoryNode() | @@ -108,7 +114,7 @@ class AmdModuleDefinition extends CallExpr { * Gets the `i`th parameter of the factory function of this module. */ private SimpleParameter getFactoryParameter(int i) { - getFactoryNode().(DataFlow::FunctionNode).getParameter(i) = DataFlow::parameterNode(result) + getFactoryNodeInternal().asExpr().(Function).getParameter(i) = result } /** diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index b1cbe224764..81bb64f272c 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -23,6 +23,10 @@ import javascript class ASTNode extends @ast_node, Locatable { override Location getLocation() { hasLocation(this, result) } + override File getFile() { + result = getLocation().getFile() // Specialized for performance reasons + } + /** Gets the first token belonging to this element. */ Token getFirstToken() { exists(Location l1, Location l2 | diff --git a/javascript/ql/src/semmle/javascript/NPM.qll b/javascript/ql/src/semmle/javascript/NPM.qll index d82200bdf31..24d3072fae1 100644 --- a/javascript/ql/src/semmle/javascript/NPM.qll +++ b/javascript/ql/src/semmle/javascript/NPM.qll @@ -190,7 +190,7 @@ class BugTrackerInfo extends JSONValue { } /** Gets the bug tracker URL. */ - string getURL() { + string getUrl() { result = this.(JSONObject).getPropStringValue("url") or result = this.(JSONString).getValue() } @@ -233,7 +233,7 @@ class ContributorInfo extends JSONValue { } /** Gets the contributor's homepage URL. */ - string getURL() { + string getUrl() { result = this.(JSONObject).getPropStringValue("url") or result = parseInfo(3) } @@ -249,7 +249,7 @@ class RepositoryInfo extends JSONObject { string getType() { result = getPropStringValue("type") } /** Gets the repository URL. */ - string getURL() { result = getPropStringValue("url") } + string getUrl() { result = getPropStringValue("url") } } /** diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 77ffdb47eca..56025b75ffb 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -168,7 +168,7 @@ module PromiseTypeTracking { * This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another. */ pragma[inline] - DataFlow::SourceNode promiseStep(DataFlow::SourceNode pred, StepSummary summary) { + DataFlow::Node promiseStep(DataFlow::Node pred, StepSummary summary) { exists(PromiseFlowStep step, string field | field = Promises::valueProp() | summary = LoadStep(field) and step.load(pred, result, field) @@ -176,7 +176,7 @@ module PromiseTypeTracking { summary = StoreStep(field) and step.store(pred, result, field) or - summary = LevelStep() and + summary = LoadStoreStep(field) and step.loadStore(pred, result, field) ) } @@ -189,9 +189,8 @@ module PromiseTypeTracking { DataFlow::SourceNode promiseStep( DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2 ) { - exists(StepSummary summary | - result = PromiseTypeTracking::promiseStep(pred, summary) and - t = t2.append(summary) + exists(DataFlow::Node mid, StepSummary summary | pred.flowsTo(mid) and t = t2.append(summary) | + result = PromiseTypeTracking::promiseStep(mid, summary) ) } diff --git a/javascript/ql/src/semmle/javascript/Variables.qll b/javascript/ql/src/semmle/javascript/Variables.qll index 5c5c3e3f115..2cbd54d1d73 100644 --- a/javascript/ql/src/semmle/javascript/Variables.qll +++ b/javascript/ql/src/semmle/javascript/Variables.qll @@ -317,6 +317,24 @@ class LocalVariable extends Variable { else result = d.getContainer() ) } + + /** + * Gets the location of a declaration of this variable. + * + * If the variable has one or more declarations, the location of the first declaration is used. + * If the variable has no declaration, the entry point of its declaring container is used. + */ + Location getLocation() { + result = + min(Location loc | + loc = getADeclaration().getLocation() + | + loc order by loc.getStartLine(), loc.getStartColumn() + ) + or + not exists(getADeclaration()) and + result = getDeclaringContainer().getEntry().getLocation() + } } /** A local variable that is not captured. */ diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 9ec2b3acf8f..e57c0764000 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -262,6 +262,17 @@ abstract class Configuration extends string { predicate isAdditionalLoadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. + */ + predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { + none() + } } /** @@ -548,6 +559,19 @@ abstract class AdditionalFlowStep extends DataFlow::Node { */ cached predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() } + + /** + * EXPERIMENTAL. This API may change in the future. + * + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. + */ + cached + predicate loadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { + loadProp = storeProp and + loadStoreStep(pred, succ, loadProp) + } } /** @@ -666,7 +690,7 @@ private predicate exploratoryFlowStep( basicLoadStep(pred, succ, _) or isAdditionalStoreStep(pred, succ, _, cfg) or isAdditionalLoadStep(pred, succ, _, cfg) or - isAdditionalLoadStoreStep(pred, succ, _, cfg) or + isAdditionalLoadStoreStep(pred, succ, _, _, cfg) or // the following three disjuncts taken together over-approximate flow through // higher-order calls callback(pred, succ) or @@ -910,14 +934,22 @@ private predicate isAdditionalStoreStep( } /** - * Holds if the property `prop` should be copied from the object `pred` to the object `succ`. + * Holds if the property `loadProp` should be copied from the object `pred` to the property `storeProp` of object `succ`. */ private predicate isAdditionalLoadStoreStep( - DataFlow::Node pred, DataFlow::Node succ, string prop, DataFlow::Configuration cfg + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp, + DataFlow::Configuration cfg ) { - any(AdditionalFlowStep s).loadStoreStep(pred, succ, prop) + any(AdditionalFlowStep s).loadStoreStep(pred, succ, loadProp, storeProp) or - cfg.isAdditionalLoadStoreStep(pred, succ, prop) + cfg.isAdditionalLoadStoreStep(pred, succ, loadProp, storeProp) + or + loadProp = storeProp and + ( + any(AdditionalFlowStep s).loadStoreStep(pred, succ, loadProp) + or + cfg.isAdditionalLoadStoreStep(pred, succ, loadProp) + ) } /** @@ -963,7 +995,7 @@ private predicate reachableFromStoreBase( s2.getEndLabel()) ) or - exists(PathSummary oldSummary, PathSummary newSummary | + exists(PathSummary newSummary, PathSummary oldSummary | reachableFromStoreBaseStep(prop, rhs, nd, cfg, oldSummary, newSummary) and summary = oldSummary.appendValuePreserving(newSummary) ) @@ -980,11 +1012,15 @@ private predicate reachableFromStoreBaseStep( string prop, DataFlow::Node rhs, DataFlow::Node nd, DataFlow::Configuration cfg, PathSummary oldSummary, PathSummary newSummary ) { - exists(DataFlow::Node mid | reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) | + exists(DataFlow::Node mid | + reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) and flowStep(mid, cfg, nd, newSummary) or - isAdditionalLoadStoreStep(mid, nd, prop, cfg) and - newSummary = PathSummary::level() + exists(string midProp | + reachableFromStoreBase(midProp, rhs, mid, cfg, oldSummary) and + isAdditionalLoadStoreStep(mid, nd, midProp, prop, cfg) and + newSummary = PathSummary::level() + ) ) } @@ -1426,6 +1462,9 @@ class MidPathNode extends PathNode, MkMidNode { or // Skip the synthetic 'this' node, as a ThisExpr will be the next node anyway nd = DataFlow::thisNode(_) + or + // Skip captured variable nodes as the successor will be a use of that variable anyway. + nd = DataFlow::capturedVariableNode(_) } } diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 5d7ce03e467..3e435b81094 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -27,6 +27,7 @@ module DataFlow { private newtype TNode = TValueNode(AST::ValueNode nd) or TSsaDefNode(SsaDefinition d) or + TCapturedVariableNode(LocalVariable v) { v.isCaptured() } or TPropNode(@property p) or TRestPatternNode(DestructuringPattern dp, Expr rest) { rest = dp.getRest() } or TDestructuringPatternNode(DestructuringPattern dp) or @@ -165,15 +166,11 @@ module DataFlow { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - filepath = "" and - startline = 0 and - startcolumn = 0 and - endline = 0 and - endcolumn = 0 + none() } /** Gets the file this data flow node comes from. */ - File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) } + File getFile() { none() } // overridden in subclasses /** Gets the start line of this data flow node. */ int getStartLine() { hasLocationInfo(_, result, _, _, _) } @@ -313,6 +310,8 @@ module DataFlow { astNode.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + override File getFile() { result = astNode.getFile() } + override string toString() { result = astNode.toString() } } @@ -337,6 +336,8 @@ module DataFlow { override string toString() { result = ssa.getSourceVariable().getName() } + override File getFile() { result = ssa.getBasicBlock().getFile() } + override ASTNode getAstNode() { none() } } @@ -361,6 +362,8 @@ module DataFlow { override string toString() { result = prop.(ASTNode).toString() } + override File getFile() { result = prop.(ASTNode).getFile() } + override ASTNode getAstNode() { result = prop } } @@ -384,6 +387,8 @@ module DataFlow { override string toString() { result = "..." + rest.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = rest } } @@ -406,6 +411,8 @@ module DataFlow { override string toString() { result = pattern.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = pattern } } @@ -429,6 +436,8 @@ module DataFlow { override string toString() { result = elt.toString() } + override File getFile() { result = pattern.getFile() } + override ASTNode getAstNode() { result = elt } } @@ -456,6 +465,8 @@ module DataFlow { override string toString() { result = elt.toString() } + override File getFile() { result = arr.getFile() } + override ASTNode getAstNode() { result = elt } } @@ -478,6 +489,8 @@ module DataFlow { } override string toString() { result = "reflective call" } + + override File getFile() { result = call.getFile() } } /** @@ -497,6 +510,8 @@ module DataFlow { } override string toString() { result = imprt.toString() } + + override File getFile() { result = imprt.getFile() } } /** @@ -924,6 +939,8 @@ module DataFlow { ) { p.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + + override File getFile() { result = p.getFile() } } /** @@ -944,6 +961,8 @@ module DataFlow { /** Gets the attribute corresponding to this data flow node. */ HTML::Attribute getAttribute() { result = attr } + + override File getFile() { result = attr.getFile() } } /** @@ -968,6 +987,8 @@ module DataFlow { * Gets the function corresponding to this exceptional return node. */ Function getFunction() { result = function } + + override File getFile() { result = function.getFile() } } /** @@ -992,6 +1013,8 @@ module DataFlow { * Gets the invocation corresponding to this exceptional return node. */ DataFlow::InvokeNode getInvocation() { result = invoke.flow() } + + override File getFile() { result = invoke.getFile() } } /** @@ -1219,8 +1242,38 @@ module DataFlow { .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) ) } + + override File getFile() { + exists(StmtContainer container | this = TThisNode(container) | result = container.getFile()) + } } + /** + * A data flow node representing a captured variable. + */ + private class CapturedVariableNode extends Node, TCapturedVariableNode { + LocalVariable variable; + + CapturedVariableNode() { this = TCapturedVariableNode(variable) } + + override BasicBlock getBasicBlock() { result = variable.getDeclaringContainer().getStartBB() } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + variable.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + override string toString() { result = variable.getName() } + } + + /** + * INTERNAL. DO NOT USE. + * + * Gets a data flow node representing the given captured variable. + */ + Node capturedVariableNode(LocalVariable variable) { result = TCapturedVariableNode(variable) } + /** * Gets the data flow node corresponding to `nd`. * @@ -1369,18 +1422,18 @@ module DataFlow { */ private predicate lvalueDefaultFlowStep(Node pred, Node succ) { exists(PropertyPattern pattern | - pred = valueNode(pattern.getDefault()) and + pred = TValueNode(pattern.getDefault()) and succ = lvalueNode(pattern.getValuePattern()) ) or exists(ArrayPattern array, int i | - pred = valueNode(array.getDefault(i)) and + pred = TValueNode(array.getDefault(i)) and succ = lvalueNode(array.getElement(i)) ) or exists(Parameter param | - pred = valueNode(param.getDefault()) and - succ = parameterNode(param) + pred = TValueNode(param.getDefault()) and + parameterNode(succ, param) ) } @@ -1434,19 +1487,23 @@ module DataFlow { or immediateFlowStep(pred, succ) or + // From an assignment or implicit initialization of a captured variable to its flow-insensitive node. + exists(SsaDefinition predDef | + pred = TSsaDefNode(predDef) and + succ = TCapturedVariableNode(predDef.getSourceVariable()) + | + predDef instanceof SsaExplicitDefinition or + predDef instanceof SsaImplicitInit + ) + or + // From a captured variable node to its flow-sensitive capture nodes + exists(SsaVariableCapture ssaCapture | + pred = TCapturedVariableNode(ssaCapture.getSourceVariable()) and + succ = TSsaDefNode(ssaCapture) + ) + or // Flow through implicit SSA nodes exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) | - // from any explicit definition or implicit init of a captured variable into - // the capturing definition - exists(SsaSourceVariable v, SsaDefinition predDef | - v = ssa.(SsaVariableCapture).getSourceVariable() and - predDef.getSourceVariable() = v and - pred = TSsaDefNode(predDef) - | - predDef instanceof SsaExplicitDefinition or - predDef instanceof SsaImplicitInit - ) - or // from the inputs of phi and pi nodes into the node itself pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition()) ) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index fecc564af89..620f4c46cdd 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -287,32 +287,32 @@ module TaintTracking { /** * A taint propagating data flow edge for assignments of the form `o[k] = v`, where * `k` is not a constant and `o` refers to some object literal; in this case, we consider - * taint to flow from `v` to any variable that refers to the object literal. + * taint to flow from `v` to that object literal. * * The rationale for this heuristic is that if properties of `o` are accessed by * computed (that is, non-constant) names, then `o` is most likely being treated as * a map, not as a real object. In this case, it makes sense to consider the entire * map to be tainted as soon as one of its entries is. */ - private class DictionaryTaintStep extends AdditionalTaintStep, DataFlow::ValueNode { - override VarAccess astNode; - DataFlow::Node source; - - DictionaryTaintStep() { - exists(AssignExpr assgn, IndexExpr idx, AbstractObjectLiteral obj | - assgn.getTarget() = idx and - idx.getBase().analyze().getAValue() = obj and - not exists(idx.getPropertyName()) and - astNode.analyze().getAValue() = obj and - source = DataFlow::valueNode(assgn.getRhs()) - ) - } + private class DictionaryTaintStep extends AdditionalTaintStep { + DictionaryTaintStep() { dictionaryTaintStep(_, this) } override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - pred = source and succ = this + succ = this and + dictionaryTaintStep(pred, succ) } } + /** Holds if there is a step `pred -> succ` used by `DictionaryTaintStep`. */ + private predicate dictionaryTaintStep(DataFlow::Node pred, DataFlow::ObjectLiteralNode succ) { + exists(AssignExpr assgn, IndexExpr idx | + assgn.getTarget() = idx and + succ.flowsToExpr(idx.getBase()) and + not exists(idx.getPropertyName()) and + pred = DataFlow::valueNode(assgn.getRhs()) + ) + } + /** * A taint propagating data flow edge for assignments of the form `c1.state.p = v`, * where `c1` is an instance of React component `C`; in this case, we consider @@ -558,8 +558,8 @@ module TaintTracking { } /** - * Holds if `params` is a `URLSearchParams` object providing access to - * the parameters encoded in `input`. + * Holds if `params` is a construction of a `URLSearchParams` that parses + * the parameters in `input`. */ predicate isUrlSearchParams(DataFlow::SourceNode params, DataFlow::Node input) { exists(DataFlow::GlobalVarRefNode urlSearchParams, NewExpr newUrlSearchParams | @@ -568,34 +568,92 @@ module TaintTracking { params.asExpr() = newUrlSearchParams and input.asExpr() = newUrlSearchParams.getArgument(0) ) - or - exists(DataFlow::NewNode newUrl | - newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and - params = newUrl.getAPropertyRead("searchParams") and - input = newUrl.getArgument(0) - ) } + /** + * A pseudo-property a `URL` that stores a value that can be obtained + * with a `get` or `getAll` call to the `searchParams` property. + */ + private string hiddenUrlPseudoProperty() { result = "$hiddenSearchPararms" } + + /** + * A pseudo-property on a `URLSearchParams` that can be obtained + * with a `get` or `getAll` call. + */ + private string getableUrlPseudoProperty() { result = "$gettableSearchPararms" } + /** * A taint propagating data flow edge arising from URL parameter parsing. */ - private class UrlSearchParamsTaintStep extends AdditionalTaintStep, DataFlow::ValueNode { - DataFlow::Node source; + private class UrlSearchParamsTaintStep extends DataFlow::AdditionalFlowStep, DataFlow::ValueNode { + /** + * Holds if `succ` is a `URLSearchParams` providing access to the + * parameters encoded in `pred`. + */ + override predicate step(DataFlow::Node pred, DataFlow::Node succ) { + isUrlSearchParams(succ, pred) and succ = this + } - UrlSearchParamsTaintStep() { - // either this is itself an `URLSearchParams` object - isUrlSearchParams(this, source) - or - // or this is a call to `get` or `getAll` on a `URLSearchParams` object - exists(DataFlow::SourceNode searchParams, string m | - isUrlSearchParams(searchParams, source) and - this = searchParams.getAMethodCall(m) and - m.matches("get%") + /** + * Holds if `pred` should be stored in the object `succ` under the property `prop`. + * + * This step is used to model 3 facts: + * 1) A `URL` constructed using `url = new URL(input)` transfers taint from `input` to `url.searchParams`, `url.hash`, and `url.search`. + * 2) Accessing the `searchParams` on a `URL` results in a `URLSearchParams` object (See the loadStoreStep method on this class and hiddenUrlPseudoProperty()) + * 3) A `URLSearchParams` object (either `url.searchParams` or `new URLSearchParams(input)`) has a tainted value, + * which can be accessed using a `get` or `getAll` call. (See getableUrlPseudoProperty()) + */ + override predicate storeStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + succ = this and + ( + ( + prop = "searchParams" or + prop = "hash" or + prop = "search" or + prop = hiddenUrlPseudoProperty() + ) and + exists(DataFlow::NewNode newUrl | succ = newUrl | + newUrl = DataFlow::globalVarRef("URL").getAnInstantiation() and + pred = newUrl.getArgument(0) + ) + or + prop = getableUrlPseudoProperty() and + isUrlSearchParams(succ, pred) ) } - override predicate step(DataFlow::Node pred, DataFlow::Node succ) { - pred = source and succ = this + /** + * Holds if the property `loadStep` should be copied from the object `pred` to the property `storeStep` of object `succ`. + * + * This step is used to copy the value of our pseudo-property that can later be accessed using a `get` or `getAll` call. + * For an expression `url.searchParams`, the property `hiddenUrlPseudoProperty()` from the `url` object is stored in the property `getableUrlPseudoProperty()` on `url.searchParams`. + */ + override predicate loadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { + succ = this and + loadProp = hiddenUrlPseudoProperty() and + storeProp = getableUrlPseudoProperty() and + exists(DataFlow::PropRead read | read = succ | + read.getPropertyName() = "searchParams" and + read.getBase() = pred + ) + } + + /** + * Holds if the property `prop` of the object `pred` should be loaded into `succ`. + * + * This step is used to load the value stored in the pseudo-property `getableUrlPseudoProperty()`. + */ + override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + succ = this and + prop = getableUrlPseudoProperty() and + // this is a call to `get` or `getAll` on a `URLSearchParams` object + exists(string m, DataFlow::MethodCallNode call | call = succ | + call.getMethodName() = m and + call.getReceiver() = pred and + m.matches("get%") + ) } } diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index ba49ac93dd5..4edd1451a5b 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -44,7 +44,7 @@ private newtype TTypeTracker = MkTypeTracker(Boolean hasCall, OptionalPropertyNa */ class TypeTracker extends TTypeTracker { Boolean hasCall; - string prop; + OptionalPropertyName prop; TypeTracker() { this = MkTypeTracker(hasCall, prop) } @@ -53,6 +53,8 @@ class TypeTracker extends TTypeTracker { TypeTracker append(StepSummary step) { step = LevelStep() and result = this or + step = LoadStoreStep(prop) and result = this + or step = CallStep() and result = MkTypeTracker(true, prop) or step = ReturnStep() and hasCall = false and result = this @@ -211,6 +213,8 @@ class TypeBackTracker extends TTypeBackTracker { TypeBackTracker prepend(StepSummary step) { step = LevelStep() and result = this or + step = LoadStoreStep(prop) and result = this + or step = CallStep() and hasReturn = false and result = this or step = ReturnStep() and result = MkTypeBackTracker(true, prop) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll index a848cd57434..25f8fb356fb 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/StepSummary.qll @@ -34,7 +34,8 @@ newtype TStepSummary = CallStep() or ReturnStep() or StoreStep(PropertyName prop) or - LoadStep(PropertyName prop) + LoadStep(PropertyName prop) or + LoadStoreStep(PropertyName prop) /** * INTERNAL: Use `TypeTracker` or `TypeBackTracker` instead. @@ -53,6 +54,8 @@ class StepSummary extends TStepSummary { exists(string prop | this = StoreStep(prop) | result = "store " + prop) or exists(string prop | this = LoadStep(prop) | result = "load " + prop) + or + exists(string prop | this = LoadStoreStep(prop) | result = "in " + prop) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 6eede4a1aa8..09445534253 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -23,14 +23,33 @@ DataFlow::SourceNode angular() { result = DataFlow::moduleImport("angular") } -pragma[noopt] +/** + * Holds if `tl` appears to be a top-level using the AngularJS library. + * + * Should not depend on the `SourceNode` class. + */ +pragma[nomagic] +private predicate isAngularTopLevel(TopLevel tl) { + exists(Import imprt | + imprt.getTopLevel() = tl and + imprt.getImportedPath().getValue() = "angular" + ) + or + exists(GlobalVarAccess global | + global.getName() = "angular" and + global.getTopLevel() = tl + ) +} + +/** + * Holds if `s` is a string in a top-level using the AngularJS library. + * + * Should not depend on the `SourceNode` class. + */ +pragma[nomagic] private predicate isAngularString(Expr s) { - exists(DataFlow::SourceNode angular, StmtContainer sc, TopLevel tl | - angular = angular() and - sc = angular.getContainer() and - tl = sc.getTopLevel() and - tl = s.getTopLevel() - | + isAngularTopLevel(s.getTopLevel()) and + ( s instanceof StringLiteral or s instanceof TemplateLiteral ) diff --git a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll index fd28cd43666..6110bb92aca 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/HTTP.qll @@ -467,10 +467,6 @@ module HTTP { abstract DataFlow::Node getASecretKey(); } - private class CookieMiddlewareInstanceAsSourceNode extends DataFlow::SourceNode::Range { - CookieMiddlewareInstanceAsSourceNode() { this instanceof CookieMiddlewareInstance } - } - /** * A key used for signed cookies, viewed as a `CryptographicKey`. */ diff --git a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll index b8c1c1e0c1f..c7efb210ab7 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LazyCache.qll @@ -6,9 +6,11 @@ import javascript module LazyCache { /** + * DEPRECATED. DO NOT USE. + * * A lazy-cache object, usually created through an expression of form `require('lazy-cache')(require)`. */ - class LazyCacheObject extends DataFlow::SourceNode { + deprecated class LazyCacheObject extends DataFlow::SourceNode { LazyCacheObject() { // Use `require` directly instead of `moduleImport` to avoid recursion. // For the same reason, avoid `Import.getImportedPath`. @@ -19,13 +21,26 @@ module LazyCache { } } + /** + * A variable containing a lazy-cache object. + */ + class LazyCacheVariable extends LocalVariable { + LazyCacheVariable() { + // To avoid recursion, this should not depend on `SourceNode`. + exists(Require req | + req.getArgument(0).getStringValue() = "lazy-cache" and + getAnAssignedExpr().(CallExpr).getCallee() = req + ) + } + } + /** * An import through `lazy-cache`. */ class LazyCacheImport extends CallExpr, Import { - LazyCacheObject cache; + LazyCacheVariable cache; - LazyCacheImport() { this = cache.getACall().asExpr() } + LazyCacheImport() { getCallee() = cache.getAnAccess() } /** Gets the name of the package as it's exposed on the lazy-cache object. */ string getLocalAlias() { @@ -39,10 +54,22 @@ module LazyCache { override PathExpr getImportedPath() { result = getArgument(0) } + private LazyCacheVariable getVariable() { result = cache } + + pragma[noopt] override DataFlow::Node getImportedModuleNode() { + this instanceof LazyCacheImport and result = this.flow() or - result = cache.getAPropertyRead(getLocalAlias()) + exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName | + // To avoid recursion, this should not depend on `SourceNode`. + variable = getVariable() and + base = variable.getAnAccess() and + access.getBase() = base and + localName = getLocalAlias() and + access.getPropertyName() = localName and + result = access.flow() + ) } } diff --git a/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll index 16c8fd851bf..5461231365f 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll @@ -14,10 +14,6 @@ module LodashUnderscore { abstract string getName(); } - private class MemberAsSourceNode extends DataFlow::SourceNode::Range { - MemberAsSourceNode() { this instanceof Member } - } - /** * An import of `lodash` or `underscore` accessing a given member of that package. */ diff --git a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll index 78393a1aabf..e368b16e433 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/NodeJSLib.qll @@ -459,7 +459,7 @@ module NodeJSLib { private class NodeJSFileSystemAccess extends FileSystemAccess, DataFlow::CallNode { string methodName; - NodeJSFileSystemAccess() { this = fsModuleMember(methodName).getACall() } + NodeJSFileSystemAccess() { this = maybePromisified(fsModuleMember(methodName)).getACall() } /** * Gets the name of the called method. @@ -586,6 +586,19 @@ module NodeJSLib { } } + /** + * Gets a possibly promisified (using `util.promisify`) version of the input `callback`. + */ + private DataFlow::SourceNode maybePromisified(DataFlow::SourceNode callback) { + result = callback + or + exists(DataFlow::CallNode promisify | + promisify = DataFlow::moduleMember("util", "promisify").getACall() + | + result = promisify and promisify.getArgument(0).getALocalSource() = callback + ) + } + /** * A call to a method from module `child_process`. */ @@ -593,7 +606,7 @@ module NodeJSLib { string methodName; ChildProcessMethodCall() { - this = DataFlow::moduleMember("child_process", methodName).getACall() + this = maybePromisified(DataFlow::moduleMember("child_process", methodName)).getACall() } private DataFlow::Node getACommandArgument(boolean shell) { diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll index deca4bd3db4..a1b2a4bf6d9 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/DomBasedXss.qll @@ -23,5 +23,31 @@ module DomBasedXss { or node instanceof Sanitizer } + + override predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string predProp, string succProp + ) { + exists(DataFlow::PropRead read | + pred = read.getBase() and + succ = read and + read.getPropertyName() = "hash" and + predProp = "hash" and + succProp = urlSuffixPseudoProperty() + ) + } + + override predicate isAdditionalLoadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { + exists(DataFlow::MethodCallNode call, string name | + name = "substr" or name = "substring" or name = "slice" + | + call.getMethodName() = name and + not call.getArgument(0).getIntValue() = 0 and + pred = call.getReceiver() and + succ = call and + prop = urlSuffixPseudoProperty() + ) + } } + + private string urlSuffixPseudoProperty() { result = "$UrlSuffix$" } } diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll index 06b0a6eb9e6..3a8a20895d8 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPath.qll @@ -206,6 +206,20 @@ module TaintedPath { dstlabel.isNormalized() ) or + // foo.replace(/(\.\.\/)*/, "") and similar + exists(DotDotSlashPrefixRemovingReplace call | + src = call.getInput() and + dst = call.getOutput() + | + // the 4 possible combinations of normalized + relative for `srclabel`, and the possible values for `dstlabel` in each case. + srclabel.isNonNormalized() and srclabel.isRelative() // raw + relative -> any() + or + srclabel.isNormalized() and srclabel.isAbsolute() and srclabel = dstlabel // normalized + absolute -> normalized + absolute + or + srclabel.isNonNormalized() and srclabel.isAbsolute() and dstlabel.isAbsolute() // raw + absolute -> raw/normalized + absolute + // normalized + relative -> none() + ) + or // path.join() exists(DataFlow::CallNode join, int n | join = NodeJSLib::Path::moduleMember("join").getACall() diff --git a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index c55fa8bad33..9ec8473fc0a 100644 --- a/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/src/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -225,7 +225,8 @@ module TaintedPath { term.getAMatchedString() = "/" or term.getAMatchedString() = "." or term.getAMatchedString() = ".." - ) + ) and + not this instanceof DotDotSlashPrefixRemovingReplace } /** @@ -239,6 +240,57 @@ module TaintedPath { DataFlow::Node getOutput() { result = output } } + /** + * A call that removes all instances of "../" in the prefix of the string. + */ + class DotDotSlashPrefixRemovingReplace extends DataFlow::CallNode { + DataFlow::Node input; + DataFlow::Node output; + + DotDotSlashPrefixRemovingReplace() { + this.getCalleeName() = "replace" and + input = getReceiver() and + output = this and + exists(RegExpLiteral literal, RegExpTerm term | + getArgument(0).getALocalSource().asExpr() = literal and + (term instanceof RegExpStar or term instanceof RegExpPlus) and + term.getChild(0) = getADotDotSlashMatcher() + | + literal.getRoot() = term + or + exists(RegExpSequence seq | seq.getNumChild() = 2 and literal.getRoot() = seq | + seq.getChild(0) instanceof RegExpCaret and + seq.getChild(1) = term + ) + ) + } + + /** + * Gets the input path to be sanitized. + */ + DataFlow::Node getInput() { result = input } + + /** + * Gets the path where prefix "../" has been removed. + */ + DataFlow::Node getOutput() { result = output } + } + + /** + * Gets a RegExpTerm that matches a variation of "../". + */ + private RegExpTerm getADotDotSlashMatcher() { + result.getAMatchedString() = "../" + or + exists(RegExpSequence seq | seq = result | + seq.getChild(0).getConstantValue() = "." and + seq.getChild(1).getConstantValue() = "." and + seq.getChild(2).getAMatchedString() = "/" + ) + or + exists(RegExpGroup group | result = group | group.getChild(0) = getADotDotSlashMatcher()) + } + /** * A call that removes all "." or ".." from a path, without also removing all forward slashes. */ diff --git a/javascript/ql/test/library-tests/Constants/Constants.expected b/javascript/ql/test/library-tests/Constants/Constants.expected index 8bb5f427ec5..cb8ff2418bc 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.expected +++ b/javascript/ql/test/library-tests/Constants/Constants.expected @@ -1,3 +1,125 @@ +getIntValue +| tst2.ts:1:21:1:21 | 1 | 1 | +| tst.js:6:1:6:1 | 1 | 1 | +| tst.js:11:1:11:2 | -1 | -1 | +| tst.js:11:2:11:2 | 1 | 1 | +| tst.js:12:2:12:2 | 0 | 0 | +| tst.js:26:3:26:3 | 0 | 0 | +| tst.js:29:6:29:6 | 0 | 0 | +| tst.js:35:1:35:1 | 1 | 1 | +| tst.js:35:5:35:5 | 2 | 2 | +| tst.js:35:9:35:9 | 3 | 3 | +| tst.js:37:1:37:3 | (1) | 1 | +| tst.js:37:2:37:2 | 1 | 1 | +| tst.js:39:4:39:4 | 1 | 1 | +| tst.js:40:1:40:1 | 1 | 1 | +| tst.js:42:1:42:1 | 1 | 1 | +| tst.js:42:4:42:4 | 2 | 2 | +| tst.js:42:7:42:7 | 3 | 3 | +| tst.js:43:4:43:4 | 2 | 2 | +| tst.js:43:7:43:7 | 3 | 3 | +| tst.js:44:1:44:1 | 1 | 1 | +| tst.js:44:7:44:7 | 3 | 3 | +| tst.js:45:1:45:1 | 1 | 1 | +| tst.js:45:4:45:4 | 2 | 2 | +| tst.js:47:5:47:5 | 1 | 1 | +| tst.js:48:7:48:7 | 1 | 1 | +| tst.js:49:6:49:6 | 1 | 1 | +| tst.js:52:5:52:9 | 1_000 | 1000 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1000000000 | +| tst.js:56:5:56:10 | 123_00 | 12300 | +| tst.js:57:5:57:10 | 12_300 | 12300 | +| tst.js:58:5:58:12 | 12345_00 | 1234500 | +| tst.js:59:5:59:12 | 123_4500 | 1234500 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 11189196 | +getFloatValue +| tst2.ts:1:21:1:21 | 1 | 1.0 | +| tst.js:6:1:6:1 | 1 | 1.0 | +| tst.js:11:2:11:2 | 1 | 1.0 | +| tst.js:12:2:12:2 | 0 | 0.0 | +| tst.js:26:3:26:3 | 0 | 0.0 | +| tst.js:29:6:29:6 | 0 | 0.0 | +| tst.js:35:1:35:1 | 1 | 1.0 | +| tst.js:35:5:35:5 | 2 | 2.0 | +| tst.js:35:9:35:9 | 3 | 3.0 | +| tst.js:37:2:37:2 | 1 | 1.0 | +| tst.js:39:4:39:4 | 1 | 1.0 | +| tst.js:40:1:40:1 | 1 | 1.0 | +| tst.js:42:1:42:1 | 1 | 1.0 | +| tst.js:42:4:42:4 | 2 | 2.0 | +| tst.js:42:7:42:7 | 3 | 3.0 | +| tst.js:43:4:43:4 | 2 | 2.0 | +| tst.js:43:7:43:7 | 3 | 3.0 | +| tst.js:44:1:44:1 | 1 | 1.0 | +| tst.js:44:7:44:7 | 3 | 3.0 | +| tst.js:45:1:45:1 | 1 | 1.0 | +| tst.js:45:4:45:4 | 2 | 2.0 | +| tst.js:47:5:47:5 | 1 | 1.0 | +| tst.js:48:7:48:7 | 1 | 1.0 | +| tst.js:49:6:49:6 | 1 | 1.0 | +| tst.js:52:5:52:9 | 1_000 | 1000.0 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123.0 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1.0E9 | +| tst.js:55:5:55:18 | 101_475_938.38 | 1.0147593838E8 | +| tst.js:56:5:56:10 | 123_00 | 12300.0 | +| tst.js:57:5:57:10 | 12_300 | 12300.0 | +| tst.js:58:5:58:12 | 12345_00 | 1234500.0 | +| tst.js:59:5:59:12 | 123_4500 | 1234500.0 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500.0 | +| tst.js:61:5:61:10 | 1e1_00 | 1.0E100 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 1.1189196E7 | +getLiteralValue +| tst2.ts:1:21:1:21 | 1 | 1 | +| tst.js:1:1:1:3 | "a" | a | +| tst.js:2:1:2:3 | "b" | b | +| tst.js:2:7:2:9 | "c" | c | +| tst.js:3:1:3:3 | "d" | d | +| tst.js:3:7:3:9 | "e" | e | +| tst.js:3:13:3:15 | "f" | f | +| tst.js:6:1:6:1 | 1 | 1 | +| tst.js:8:1:8:5 | false | false | +| tst.js:9:1:9:4 | true | true | +| tst.js:11:2:11:2 | 1 | 1 | +| tst.js:12:2:12:2 | 0 | 0 | +| tst.js:14:1:14:4 | null | null | +| tst.js:20:1:20:3 | /x/ | /x/ | +| tst.js:24:5:24:7 | "x" | x | +| tst.js:26:3:26:3 | 0 | 0 | +| tst.js:29:6:29:6 | 0 | 0 | +| tst.js:35:1:35:1 | 1 | 1 | +| tst.js:35:5:35:5 | 2 | 2 | +| tst.js:35:9:35:9 | 3 | 3 | +| tst.js:37:2:37:2 | 1 | 1 | +| tst.js:39:4:39:4 | 1 | 1 | +| tst.js:40:1:40:1 | 1 | 1 | +| tst.js:42:1:42:1 | 1 | 1 | +| tst.js:42:4:42:4 | 2 | 2 | +| tst.js:42:7:42:7 | 3 | 3 | +| tst.js:43:4:43:4 | 2 | 2 | +| tst.js:43:7:43:7 | 3 | 3 | +| tst.js:44:1:44:1 | 1 | 1 | +| tst.js:44:7:44:7 | 3 | 3 | +| tst.js:45:1:45:1 | 1 | 1 | +| tst.js:45:4:45:4 | 2 | 2 | +| tst.js:47:5:47:5 | 1 | 1 | +| tst.js:48:7:48:7 | 1 | 1 | +| tst.js:49:6:49:6 | 1 | 1 | +| tst.js:52:5:52:9 | 1_000 | 1000 | +| tst.js:53:5:53:13 | 1_000_123 | 1000123 | +| tst.js:54:5:54:17 | 1_000_000_000 | 1000000000 | +| tst.js:55:5:55:18 | 101_475_938.38 | 1.0147593838E8 | +| tst.js:56:5:56:10 | 123_00 | 12300 | +| tst.js:57:5:57:10 | 12_300 | 12300 | +| tst.js:58:5:58:12 | 12345_00 | 1234500 | +| tst.js:59:5:59:12 | 123_4500 | 1234500 | +| tst.js:60:5:60:13 | 1_234_500 | 1234500 | +| tst.js:61:5:61:10 | 1e1_00 | 1.0E100 | +| tst.js:62:5:62:14 | 0xaa_bb_cc | 11189196 | +#select +| tst2.ts:1:13:1:21 | 1 | +| tst2.ts:1:21:1:21 | 1 | | tst.js:1:1:1:3 | "a" | | tst.js:2:1:2:3 | "b" | | tst.js:2:1:2:9 | "b" + "c" | @@ -59,5 +181,25 @@ | tst.js:48:1:48:7 | x.p = 1 | | tst.js:48:7:48:7 | 1 | | tst.js:49:6:49:6 | 1 | -| tst.ts:1:13:1:21 | 1 | -| tst.ts:1:21:1:21 | 1 | +| tst.js:52:1:52:9 | x = 1_000 | +| tst.js:52:5:52:9 | 1_000 | +| tst.js:53:1:53:13 | x = 1_000_123 | +| tst.js:53:5:53:13 | 1_000_123 | +| tst.js:54:1:54:17 | x = 1_000_000_000 | +| tst.js:54:5:54:17 | 1_000_000_000 | +| tst.js:55:1:55:18 | x = 101_475_938.38 | +| tst.js:55:5:55:18 | 101_475_938.38 | +| tst.js:56:1:56:10 | x = 123_00 | +| tst.js:56:5:56:10 | 123_00 | +| tst.js:57:1:57:10 | x = 12_300 | +| tst.js:57:5:57:10 | 12_300 | +| tst.js:58:1:58:12 | x = 12345_00 | +| tst.js:58:5:58:12 | 12345_00 | +| tst.js:59:1:59:12 | x = 123_4500 | +| tst.js:59:5:59:12 | 123_4500 | +| tst.js:60:1:60:13 | x = 1_234_500 | +| tst.js:60:5:60:13 | 1_234_500 | +| tst.js:61:1:61:10 | x = 1e1_00 | +| tst.js:61:5:61:10 | 1e1_00 | +| tst.js:62:1:62:14 | x = 0xaa_bb_cc | +| tst.js:62:5:62:14 | 0xaa_bb_cc | diff --git a/javascript/ql/test/library-tests/Constants/Constants.ql b/javascript/ql/test/library-tests/Constants/Constants.ql index dcd49275a86..0f8b338d9ad 100644 --- a/javascript/ql/test/library-tests/Constants/Constants.ql +++ b/javascript/ql/test/library-tests/Constants/Constants.ql @@ -2,3 +2,9 @@ import javascript from ConstantExpr c select c + +query int getIntValue(Expr e) { result = e.getIntValue() } + +query float getFloatValue(NumberLiteral e) { result = e.getFloatValue() } + +query string getLiteralValue(Literal lit) { result = lit.getValue() } diff --git a/javascript/ql/test/library-tests/Constants/tst.js b/javascript/ql/test/library-tests/Constants/tst.js index 0a24e13abc1..06304139c75 100644 --- a/javascript/ql/test/library-tests/Constants/tst.js +++ b/javascript/ql/test/library-tests/Constants/tst.js @@ -48,3 +48,15 @@ x = 1; x.p = 1; x += 1; x += x; + +x = 1_000; +x = 1_000_123; +x = 1_000_000_000; +x = 101_475_938.38; +x = 123_00; +x = 12_300; +x = 12345_00; +x = 123_4500; +x = 1_234_500; +x = 1e1_00; +x = 0xaa_bb_cc; diff --git a/javascript/ql/test/library-tests/Constants/tst.ts b/javascript/ql/test/library-tests/Constants/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/Constants/tst.ts rename to javascript/ql/test/library-tests/Constants/tst2.ts diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected index b53738c569a..acfd9f12beb 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.expected @@ -1 +1,2 @@ | tst.js:4:15:4:22 | "source" | tst.js:9:7:9:24 | readTaint(tainted) | +| tst.js:4:15:4:22 | "source" | tst.js:15:7:15:20 | tainted3.other | diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql index 0bde5a737a6..2c56d41ab4d 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/test.ql @@ -19,6 +19,18 @@ class Configuration extends TaintTracking::Configuration { ) and prop = "bar" } + + // calling .copy("foo", "bar") actually moves a property from "foo" to "bar". + override predicate isAdditionalLoadStoreStep( + DataFlow::Node pred, DataFlow::Node succ, string loadProp, string storeProp + ) { + exists(DataFlow::MethodCallNode call | + call.getMethodName() = "copy" and call = succ and pred = call.getReceiver() + | + call.getArgument(0).mayHaveStringValue(loadProp) and + call.getArgument(1).mayHaveStringValue(storeProp) + ) + } } from DataFlow::Node pred, DataFlow::Node succ, Configuration cfg diff --git a/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js b/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js index c3fff1b4187..95806a2122d 100644 --- a/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js +++ b/javascript/ql/test/library-tests/CustomLoadStoreSteps/tst.js @@ -6,5 +6,15 @@ function readTaint(x) { return x.foo; } - sink(readTaint(tainted)); + sink(readTaint(tainted)); // NOT OK + + + var tainted2 = {myProp: source}; + + var tainted3 = tainted2.copy("myProp", "other"); + sink(tainted3.other); // NOT OK. + + var tainted4 = tainted2.copy("other", "myProp"); // does nothing, there is no "other" on tainted2. + sink(tainted4.other); // OK. + })(); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected index b7da1347fce..c5e91b074fe 100644 --- a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected +++ b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected @@ -35,6 +35,36 @@ | sources.js:11:14:11:16 | key | sources.js:11:14:11:16 | key | | sources.js:11:23:11:27 | array | sources.js:11:23:11:27 | array | | sources.js:11:32:11:34 | key | sources.js:11:32:11:34 | key | +| tst2.ts:1:18:1:18 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:2:14:2:14 | x | tst2.ts:2:14:2:14 | x | +| tst2.ts:2:14:2:19 | x = 42 | tst2.ts:2:14:2:19 | x = 42 | +| tst2.ts:2:18:2:19 | 42 | tst2.ts:2:18:2:19 | 42 | +| tst2.ts:3:3:3:6 | setX | tst2.ts:3:3:3:6 | setX | +| tst2.ts:3:3:3:8 | setX() | tst2.ts:3:3:3:8 | setX() | +| tst2.ts:4:3:4:3 | x | tst2.ts:4:3:4:3 | x | +| tst2.ts:7:10:7:13 | setX | tst2.ts:7:10:7:13 | setX | +| tst2.ts:8:3:8:3 | A | tst2.ts:8:3:8:3 | A | +| tst2.ts:8:3:8:5 | A.x | tst2.ts:8:3:8:5 | A.x | +| tst2.ts:8:3:8:10 | A.x = 23 | tst2.ts:8:3:8:10 | A.x = 23 | +| tst2.ts:8:5:8:5 | x | tst2.ts:8:5:8:5 | x | +| tst2.ts:8:9:8:10 | 23 | tst2.ts:8:9:8:10 | 23 | +| tst2.ts:11:5:11:7 | nd2 | tst2.ts:11:5:11:7 | nd2 | +| tst2.ts:11:5:11:23 | nd2 = A.x as number | tst2.ts:11:5:11:23 | nd2 = A.x as number | +| tst2.ts:11:11:11:11 | A | tst2.ts:11:11:11:11 | A | +| tst2.ts:11:11:11:13 | A.x | tst2.ts:11:11:11:13 | A.x | +| tst2.ts:11:11:11:23 | A.x as number | tst2.ts:11:11:11:23 | A.x as number | +| tst2.ts:11:13:11:13 | x | tst2.ts:11:13:11:13 | x | +| tst2.ts:13:7:13:16 | StringList | tst2.ts:13:7:13:16 | StringList | +| tst2.ts:13:26:13:29 | List | tst2.ts:13:26:13:29 | List | +| tst2.ts:13:26:13:37 | List | tst2.ts:13:26:13:37 | List | +| tst2.ts:13:39:13:38 | (...arg ... rgs); } | tst2.ts:13:39:13:38 | (...arg ... rgs); } | +| tst2.ts:13:39:13:38 | ...args | tst2.ts:13:39:13:38 | ...args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | constructor | tst2.ts:13:39:13:38 | constructor | +| tst2.ts:13:39:13:38 | super | tst2.ts:13:39:13:38 | super | +| tst2.ts:13:39:13:38 | super(...args) | tst2.ts:13:39:13:38 | super(...args) | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | @@ -289,33 +319,3 @@ | tst.js:115:1:115:12 | Array.call() | tst.js:115:1:115:12 | Array.call() | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | | tst.js:115:7:115:10 | call | tst.js:115:7:115:10 | call | -| tst.ts:1:18:1:18 | A | tst.ts:1:18:1:18 | A | -| tst.ts:2:14:2:14 | x | tst.ts:2:14:2:14 | x | -| tst.ts:2:14:2:19 | x = 42 | tst.ts:2:14:2:19 | x = 42 | -| tst.ts:2:18:2:19 | 42 | tst.ts:2:18:2:19 | 42 | -| tst.ts:3:3:3:6 | setX | tst.ts:3:3:3:6 | setX | -| tst.ts:3:3:3:8 | setX() | tst.ts:3:3:3:8 | setX() | -| tst.ts:4:3:4:3 | x | tst.ts:4:3:4:3 | x | -| tst.ts:7:10:7:13 | setX | tst.ts:7:10:7:13 | setX | -| tst.ts:8:3:8:3 | A | tst.ts:8:3:8:3 | A | -| tst.ts:8:3:8:5 | A.x | tst.ts:8:3:8:5 | A.x | -| tst.ts:8:3:8:10 | A.x = 23 | tst.ts:8:3:8:10 | A.x = 23 | -| tst.ts:8:5:8:5 | x | tst.ts:8:5:8:5 | x | -| tst.ts:8:9:8:10 | 23 | tst.ts:8:9:8:10 | 23 | -| tst.ts:11:5:11:7 | nd2 | tst.ts:11:5:11:7 | nd2 | -| tst.ts:11:5:11:23 | nd2 = A.x as number | tst.ts:11:5:11:23 | nd2 = A.x as number | -| tst.ts:11:11:11:11 | A | tst.ts:11:11:11:11 | A | -| tst.ts:11:11:11:13 | A.x | tst.ts:11:11:11:13 | A.x | -| tst.ts:11:11:11:23 | A.x as number | tst.ts:11:11:11:23 | A.x as number | -| tst.ts:11:13:11:13 | x | tst.ts:11:13:11:13 | x | -| tst.ts:13:7:13:16 | StringList | tst.ts:13:7:13:16 | StringList | -| tst.ts:13:26:13:29 | List | tst.ts:13:26:13:29 | List | -| tst.ts:13:26:13:37 | List | tst.ts:13:26:13:37 | List | -| tst.ts:13:39:13:38 | (...arg ... rgs); } | tst.ts:13:39:13:38 | (...arg ... rgs); } | -| tst.ts:13:39:13:38 | ...args | tst.ts:13:39:13:38 | ...args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | constructor | tst.ts:13:39:13:38 | constructor | -| tst.ts:13:39:13:38 | super | tst.ts:13:39:13:38 | super | -| tst.ts:13:39:13:38 | super(...args) | tst.ts:13:39:13:38 | super(...args) | diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index 31e11c60b74..fbc30cb0ec0 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -12,19 +12,34 @@ | sources.js:10:12:10:14 | key | sources.js:10:28:10:30 | key | | sources.js:11:12:11:18 | key | sources.js:11:32:11:34 | key | | sources.js:11:14:11:16 | key | sources.js:11:12:11:18 | key | -| tst.js:1:1:1:1 | x | tst.js:28:2:28:1 | x | -| tst.js:1:1:1:1 | x | tst.js:32:1:32:0 | x | +| tst2.ts:1:1:1:1 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:1:1:1:1 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:1:8:5:1 | A | tst2.ts:1:18:1:18 | A | +| tst2.ts:1:8:5:1 | A | tst2.ts:11:11:11:11 | A | +| tst2.ts:1:8:5:1 | namespa ... lysed\\n} | tst2.ts:1:8:5:1 | A | +| tst2.ts:1:18:1:18 | A | tst2.ts:7:1:7:0 | A | +| tst2.ts:2:14:2:19 | x | tst2.ts:4:3:4:3 | x | +| tst2.ts:2:18:2:19 | 42 | tst2.ts:2:14:2:19 | x | +| tst2.ts:7:1:7:0 | A | tst2.ts:8:3:8:3 | A | +| tst2.ts:7:1:9:1 | functio ... = 23;\\n} | tst2.ts:7:10:7:13 | setX | +| tst2.ts:7:10:7:13 | setX | tst2.ts:3:3:3:6 | setX | +| tst2.ts:8:9:8:10 | 23 | tst2.ts:8:3:8:10 | A.x = 23 | +| tst2.ts:11:11:11:13 | A.x | tst2.ts:11:11:11:23 | A.x as number | +| tst2.ts:13:26:13:29 | List | tst2.ts:13:26:13:37 | List | +| tst2.ts:13:39:13:38 | args | tst2.ts:13:39:13:38 | args | +| tst.js:1:1:1:1 | x | tst.js:3:5:3:5 | x | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:7:1:7:2 | fs | | tst.js:1:10:1:11 | fs | tst.js:22:24:22:25 | fs | +| tst.js:3:5:3:5 | x | tst.js:28:2:28:1 | x | +| tst.js:3:5:3:5 | x | tst.js:32:1:32:0 | x | +| tst.js:3:5:3:10 | x | tst.js:3:5:3:5 | x | | tst.js:3:5:3:10 | x | tst.js:8:1:8:1 | x | | tst.js:3:5:3:10 | x | tst.js:9:2:9:2 | x | | tst.js:3:5:3:10 | x | tst.js:10:1:10:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | | tst.js:3:5:3:10 | x | tst.js:11:1:11:1 | x | -| tst.js:3:5:3:10 | x | tst.js:28:2:28:1 | x | -| tst.js:3:5:3:10 | x | tst.js:32:1:32:0 | x | | tst.js:3:9:3:10 | 42 | tst.js:3:5:3:10 | x | | tst.js:4:5:4:12 | y | tst.js:10:4:10:4 | y | | tst.js:4:5:4:12 | y | tst.js:11:6:11:6 | y | @@ -61,9 +76,8 @@ | tst.js:22:5:22:25 | readFileSync | tst.js:23:1:23:12 | readFileSync | | tst.js:22:7:22:18 | readFileSync | tst.js:22:5:22:25 | readFileSync | | tst.js:22:24:22:25 | fs | tst.js:22:5:22:20 | { readFileSync } | +| tst.js:25:1:25:3 | x | tst.js:3:5:3:5 | x | | tst.js:25:1:25:3 | x | tst.js:26:1:26:1 | x | -| tst.js:25:1:25:3 | x | tst.js:28:2:28:1 | x | -| tst.js:25:1:25:3 | x | tst.js:32:1:32:0 | x | | tst.js:25:1:25:3 | x | tst.js:57:7:57:7 | x | | tst.js:25:1:25:3 | x | tst.js:58:11:58:11 | x | | tst.js:25:1:25:3 | x | tst.js:105:1:105:1 | x | @@ -147,17 +161,3 @@ | tst.js:111:29:111:31 | o2c | tst.js:111:6:111:38 | v2c | | tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | -| tst.ts:1:1:1:1 | A | tst.ts:1:18:1:18 | A | -| tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:8:5:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:8:5:1 | A | tst.ts:11:11:11:11 | A | -| tst.ts:1:8:5:1 | namespa ... lysed\\n} | tst.ts:1:8:5:1 | A | -| tst.ts:2:14:2:19 | x | tst.ts:4:3:4:3 | x | -| tst.ts:2:18:2:19 | 42 | tst.ts:2:14:2:19 | x | -| tst.ts:7:1:7:0 | A | tst.ts:8:3:8:3 | A | -| tst.ts:7:1:9:1 | functio ... = 23;\\n} | tst.ts:7:10:7:13 | setX | -| tst.ts:7:10:7:13 | setX | tst.ts:3:3:3:6 | setX | -| tst.ts:8:9:8:10 | 23 | tst.ts:8:3:8:10 | A.x = 23 | -| tst.ts:11:11:11:13 | A.x | tst.ts:11:11:11:23 | A.x as number | -| tst.ts:13:26:13:29 | List | tst.ts:13:26:13:37 | List | -| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | diff --git a/javascript/ql/test/library-tests/DataFlow/getIntValue.expected b/javascript/ql/test/library-tests/DataFlow/getIntValue.expected index 18ed3923069..fdeffe0b52e 100644 --- a/javascript/ql/test/library-tests/DataFlow/getIntValue.expected +++ b/javascript/ql/test/library-tests/DataFlow/getIntValue.expected @@ -1,6 +1,8 @@ | eval.js:2:11:2:12 | 42 | 42 | | sources.js:4:12:4:13 | 19 | 19 | | sources.js:5:4:5:5 | 23 | 23 | +| tst2.ts:2:18:2:19 | 42 | 42 | +| tst2.ts:8:9:8:10 | 23 | 23 | | tst.js:3:9:3:10 | 42 | 42 | | tst.js:51:11:51:12 | 42 | 42 | | tst.js:65:9:65:10 | 42 | 42 | @@ -11,5 +13,3 @@ | tst.js:103:6:103:7 | 19 | 19 | | tst.js:103:10:103:11 | 23 | 23 | | tst.js:103:14:103:14 | 0 | 0 | -| tst.ts:2:18:2:19 | 42 | 42 | -| tst.ts:8:9:8:10 | 23 | 23 | diff --git a/javascript/ql/test/library-tests/DataFlow/incomplete.expected b/javascript/ql/test/library-tests/DataFlow/incomplete.expected index 35413033fe7..040126f8c69 100644 --- a/javascript/ql/test/library-tests/DataFlow/incomplete.expected +++ b/javascript/ql/test/library-tests/DataFlow/incomplete.expected @@ -13,6 +13,18 @@ | sources.js:10:12:10:14 | key | heap | | sources.js:11:12:11:18 | key | heap | | sources.js:11:14:11:16 | key | heap | +| tst2.ts:2:14:2:19 | x | namespace | +| tst2.ts:3:3:3:8 | exceptional return of setX() | call | +| tst2.ts:3:3:3:8 | setX() | call | +| tst2.ts:7:1:9:1 | exceptional return of function setX | call | +| tst2.ts:8:3:8:5 | A.x | heap | +| tst2.ts:11:11:11:13 | A.x | heap | +| tst2.ts:13:26:13:29 | List | global | +| tst2.ts:13:39:13:38 | args | call | +| tst2.ts:13:39:13:38 | exceptional return of default constructor of class StringList | call | +| tst2.ts:13:39:13:38 | exceptional return of super(...args) | call | +| tst2.ts:13:39:13:38 | super | call | +| tst2.ts:13:39:13:38 | super(...args) | call | | tst.js:1:10:1:11 | fs | import | | tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | call | | tst.js:16:2:20:1 | exceptional return of function f | call | @@ -92,15 +104,3 @@ | tst.js:115:1:115:10 | Array.call | heap | | tst.js:115:1:115:12 | Array.call() | call | | tst.js:115:1:115:12 | exceptional return of Array.call() | call | -| tst.ts:2:14:2:19 | x | namespace | -| tst.ts:3:3:3:8 | exceptional return of setX() | call | -| tst.ts:3:3:3:8 | setX() | call | -| tst.ts:7:1:9:1 | exceptional return of function setX | call | -| tst.ts:8:3:8:5 | A.x | heap | -| tst.ts:11:11:11:13 | A.x | heap | -| tst.ts:13:26:13:29 | List | global | -| tst.ts:13:39:13:38 | args | call | -| tst.ts:13:39:13:38 | exceptional return of default constructor of class StringList | call | -| tst.ts:13:39:13:38 | exceptional return of super(...args) | call | -| tst.ts:13:39:13:38 | super | call | -| tst.ts:13:39:13:38 | super(...args) | call | diff --git a/javascript/ql/test/library-tests/DataFlow/parameters.expected b/javascript/ql/test/library-tests/DataFlow/parameters.expected index 31bab07c4e2..34cc8e6bb66 100644 --- a/javascript/ql/test/library-tests/DataFlow/parameters.expected +++ b/javascript/ql/test/library-tests/DataFlow/parameters.expected @@ -1,8 +1,8 @@ | sources.js:1:6:1:6 | x | | sources.js:3:11:3:11 | x | | sources.js:9:14:9:18 | array | +| tst2.ts:13:39:13:38 | args | | tst.js:16:13:16:13 | a | | tst.js:32:12:32:12 | b | | tst.js:87:11:87:24 | { p: x, ...o } | | tst.js:98:11:98:24 | [ x, ...rest ] | -| tst.ts:13:39:13:38 | args | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.expected b/javascript/ql/test/library-tests/DataFlow/sources.expected index 37a54027371..ff60d49cf58 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.expected +++ b/javascript/ql/test/library-tests/DataFlow/sources.expected @@ -19,6 +19,18 @@ | sources.js:10:12:10:14 | key | | sources.js:11:12:11:18 | { key } | | sources.js:11:14:11:16 | key | +| tst2.ts:1:1:1:0 | this | +| tst2.ts:3:3:3:8 | setX() | +| tst2.ts:7:1:7:0 | this | +| tst2.ts:7:1:9:1 | functio ... = 23;\\n} | +| tst2.ts:8:3:8:5 | A.x | +| tst2.ts:11:11:11:13 | A.x | +| tst2.ts:13:1:13:40 | class S ... ing> {} | +| tst2.ts:13:26:13:29 | List | +| tst2.ts:13:39:13:38 | (...arg ... rgs); } | +| tst2.ts:13:39:13:38 | args | +| tst2.ts:13:39:13:38 | super(...args) | +| tst2.ts:13:39:13:38 | this | | tst.js:1:1:1:0 | this | | tst.js:1:1:1:24 | import ... m 'fs'; | | tst.js:1:10:1:11 | fs | @@ -105,15 +117,3 @@ | tst.js:115:1:115:10 | Array.call | | tst.js:115:1:115:12 | Array.call() | | tst.js:115:1:115:12 | reflective call | -| tst.ts:1:1:1:0 | this | -| tst.ts:3:3:3:8 | setX() | -| tst.ts:7:1:7:0 | this | -| tst.ts:7:1:9:1 | functio ... = 23;\\n} | -| tst.ts:8:3:8:5 | A.x | -| tst.ts:11:11:11:13 | A.x | -| tst.ts:13:1:13:40 | class S ... ing> {} | -| tst.ts:13:26:13:29 | List | -| tst.ts:13:39:13:38 | (...arg ... rgs); } | -| tst.ts:13:39:13:38 | args | -| tst.ts:13:39:13:38 | super(...args) | -| tst.ts:13:39:13:38 | this | diff --git a/javascript/ql/test/library-tests/DataFlow/tst.ts b/javascript/ql/test/library-tests/DataFlow/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/DataFlow/tst.ts rename to javascript/ql/test/library-tests/DataFlow/tst2.ts diff --git a/javascript/ql/test/library-tests/Decorators/Decoratable.expected b/javascript/ql/test/library-tests/Decorators/Decoratable.expected index 7fe95e7e08a..3f2f33e6123 100644 --- a/javascript/ql/test/library-tests/Decorators/Decoratable.expected +++ b/javascript/ql/test/library-tests/Decorators/Decoratable.expected @@ -1,15 +1,15 @@ +| tst2.ts:7:9:7:9 | a | 0 | tst2.ts:7:6:7:7 | @A | +| tst2.ts:8:12:8:13 | ab | 0 | tst2.ts:8:6:8:7 | @A | +| tst2.ts:8:12:8:13 | ab | 1 | tst2.ts:8:9:8:10 | @B | +| tst2.ts:10:15:10:15 | a | 0 | tst2.ts:10:12:10:13 | @A | +| tst2.ts:11:18:11:19 | ab | 0 | tst2.ts:11:12:11:13 | @A | +| tst2.ts:11:18:11:19 | ab | 1 | tst2.ts:11:15:11:16 | @B | +| tst2.ts:13:9:13:9 | a | 0 | tst2.ts:13:6:13:7 | @A | +| tst2.ts:13:15:13:15 | b | 0 | tst2.ts:13:12:13:13 | @B | +| tst2.ts:14:9:14:9 | a | 0 | tst2.ts:14:6:14:7 | @A | +| tst2.ts:14:18:14:19 | bc | 0 | tst2.ts:14:12:14:13 | @B | +| tst2.ts:14:18:14:19 | bc | 1 | tst2.ts:14:15:14:16 | @C | | tst.js:1:7:3:1 | class C ... ) { }\\n} | 0 | tst.js:1:1:1:2 | @A | | tst.js:1:7:3:1 | class C ... ) { }\\n} | 1 | tst.js:1:4:1:5 | @B | | tst.js:2:19:2:25 | m() { } | 0 | tst.js:2:3:2:17 | @testable(true) | | tst.js:7:3:7:25 | get bar ... rn 42 } | 0 | tst.js:6:3:6:6 | @Foo | -| tst.ts:7:9:7:9 | a | 0 | tst.ts:7:6:7:7 | @A | -| tst.ts:8:12:8:13 | ab | 0 | tst.ts:8:6:8:7 | @A | -| tst.ts:8:12:8:13 | ab | 1 | tst.ts:8:9:8:10 | @B | -| tst.ts:10:15:10:15 | a | 0 | tst.ts:10:12:10:13 | @A | -| tst.ts:11:18:11:19 | ab | 0 | tst.ts:11:12:11:13 | @A | -| tst.ts:11:18:11:19 | ab | 1 | tst.ts:11:15:11:16 | @B | -| tst.ts:13:9:13:9 | a | 0 | tst.ts:13:6:13:7 | @A | -| tst.ts:13:15:13:15 | b | 0 | tst.ts:13:12:13:13 | @B | -| tst.ts:14:9:14:9 | a | 0 | tst.ts:14:6:14:7 | @A | -| tst.ts:14:18:14:19 | bc | 0 | tst.ts:14:12:14:13 | @B | -| tst.ts:14:18:14:19 | bc | 1 | tst.ts:14:15:14:16 | @C | diff --git a/javascript/ql/test/library-tests/Decorators/Decorator.expected b/javascript/ql/test/library-tests/Decorators/Decorator.expected index 0027eebc756..70fc86830f5 100644 --- a/javascript/ql/test/library-tests/Decorators/Decorator.expected +++ b/javascript/ql/test/library-tests/Decorators/Decorator.expected @@ -1,15 +1,15 @@ +| tst2.ts:7:6:7:7 | @A | tst2.ts:7:7:7:7 | A | tst2.ts:7:9:7:9 | a | +| tst2.ts:8:6:8:7 | @A | tst2.ts:8:7:8:7 | A | tst2.ts:8:12:8:13 | ab | +| tst2.ts:8:9:8:10 | @B | tst2.ts:8:10:8:10 | B | tst2.ts:8:12:8:13 | ab | +| tst2.ts:10:12:10:13 | @A | tst2.ts:10:13:10:13 | A | tst2.ts:10:15:10:15 | a | +| tst2.ts:11:12:11:13 | @A | tst2.ts:11:13:11:13 | A | tst2.ts:11:18:11:19 | ab | +| tst2.ts:11:15:11:16 | @B | tst2.ts:11:16:11:16 | B | tst2.ts:11:18:11:19 | ab | +| tst2.ts:13:6:13:7 | @A | tst2.ts:13:7:13:7 | A | tst2.ts:13:9:13:9 | a | +| tst2.ts:13:12:13:13 | @B | tst2.ts:13:13:13:13 | B | tst2.ts:13:15:13:15 | b | +| tst2.ts:14:6:14:7 | @A | tst2.ts:14:7:14:7 | A | tst2.ts:14:9:14:9 | a | +| tst2.ts:14:12:14:13 | @B | tst2.ts:14:13:14:13 | B | tst2.ts:14:18:14:19 | bc | +| tst2.ts:14:15:14:16 | @C | tst2.ts:14:16:14:16 | C | tst2.ts:14:18:14:19 | bc | | tst.js:1:1:1:2 | @A | tst.js:1:2:1:2 | A | tst.js:1:7:3:1 | class C ... ) { }\\n} | | tst.js:1:4:1:5 | @B | tst.js:1:5:1:5 | B | tst.js:1:7:3:1 | class C ... ) { }\\n} | | tst.js:2:3:2:17 | @testable(true) | tst.js:2:4:2:17 | testable(true) | tst.js:2:19:2:25 | m() { } | | tst.js:6:3:6:6 | @Foo | tst.js:6:4:6:6 | Foo | tst.js:7:3:7:25 | get bar ... rn 42 } | -| tst.ts:7:6:7:7 | @A | tst.ts:7:7:7:7 | A | tst.ts:7:9:7:9 | a | -| tst.ts:8:6:8:7 | @A | tst.ts:8:7:8:7 | A | tst.ts:8:12:8:13 | ab | -| tst.ts:8:9:8:10 | @B | tst.ts:8:10:8:10 | B | tst.ts:8:12:8:13 | ab | -| tst.ts:10:12:10:13 | @A | tst.ts:10:13:10:13 | A | tst.ts:10:15:10:15 | a | -| tst.ts:11:12:11:13 | @A | tst.ts:11:13:11:13 | A | tst.ts:11:18:11:19 | ab | -| tst.ts:11:15:11:16 | @B | tst.ts:11:16:11:16 | B | tst.ts:11:18:11:19 | ab | -| tst.ts:13:6:13:7 | @A | tst.ts:13:7:13:7 | A | tst.ts:13:9:13:9 | a | -| tst.ts:13:12:13:13 | @B | tst.ts:13:13:13:13 | B | tst.ts:13:15:13:15 | b | -| tst.ts:14:6:14:7 | @A | tst.ts:14:7:14:7 | A | tst.ts:14:9:14:9 | a | -| tst.ts:14:12:14:13 | @B | tst.ts:14:13:14:13 | B | tst.ts:14:18:14:19 | bc | -| tst.ts:14:15:14:16 | @C | tst.ts:14:16:14:16 | C | tst.ts:14:18:14:19 | bc | diff --git a/javascript/ql/test/library-tests/Decorators/tst.ts b/javascript/ql/test/library-tests/Decorators/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/Decorators/tst.ts rename to javascript/ql/test/library-tests/Decorators/tst2.ts diff --git a/javascript/ql/test/library-tests/FileTypes/FileTypes.expected b/javascript/ql/test/library-tests/FileTypes/FileTypes.expected index 45ab1533acb..455bbdb6e33 100644 --- a/javascript/ql/test/library-tests/FileTypes/FileTypes.expected +++ b/javascript/ql/test/library-tests/FileTypes/FileTypes.expected @@ -1,14 +1,14 @@ +| jsTest.js:0:0:0:0 | jsTest.js | javascript | +| jsxTest.jsx:0:0:0:0 | jsxTest.jsx | javascript | +| mjsTest.mjs:0:0:0:0 | mjsTest.mjs | javascript | | test.htm:0:0:0:0 | test.htm | html | | test.html:0:0:0:0 | test.html | html | -| test.js:0:0:0:0 | test.js | javascript | | test.json:0:0:0:0 | test.json | json | -| test.jsx:0:0:0:0 | test.jsx | javascript | -| test.mjs:0:0:0:0 | test.mjs | javascript | | test.raml:0:0:0:0 | test.raml | yaml | -| test.ts:0:0:0:0 | test.ts | typescript | -| test.tsx:0:0:0:0 | test.tsx | typescript | | test.vue:0:0:0:0 | test.vue | html | | test.xhtm:0:0:0:0 | test.xhtm | html | | test.xhtml:0:0:0:0 | test.xhtml | html | | test.yaml:0:0:0:0 | test.yaml | yaml | | test.yml:0:0:0:0 | test.yml | yaml | +| tsTest.ts:0:0:0:0 | tsTest.ts | typescript | +| tsxTest.tsx:0:0:0:0 | tsxTest.tsx | typescript | diff --git a/javascript/ql/test/library-tests/FileTypes/test.jsx b/javascript/ql/test/library-tests/FileTypes/jsTest.js similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.jsx rename to javascript/ql/test/library-tests/FileTypes/jsTest.js diff --git a/javascript/ql/test/library-tests/FileTypes/test.mjs b/javascript/ql/test/library-tests/FileTypes/jsxTest.jsx similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.mjs rename to javascript/ql/test/library-tests/FileTypes/jsxTest.jsx diff --git a/javascript/ql/test/library-tests/FileTypes/test.ts b/javascript/ql/test/library-tests/FileTypes/mjsTest.mjs similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.ts rename to javascript/ql/test/library-tests/FileTypes/mjsTest.mjs diff --git a/javascript/ql/test/library-tests/FileTypes/test.tsx b/javascript/ql/test/library-tests/FileTypes/tsTest.ts similarity index 100% rename from javascript/ql/test/library-tests/FileTypes/test.tsx rename to javascript/ql/test/library-tests/FileTypes/tsTest.ts diff --git a/javascript/ql/test/library-tests/FileTypes/tsxTest.tsx b/javascript/ql/test/library-tests/FileTypes/tsxTest.tsx new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index 531faf562bd..ceea3b05389 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -272,6 +272,10 @@ | ts.ts:1:16:1:25 | class A | | ts.ts:1:16:1:25 | instance of class A | | ts.ts:1:24:1:23 | default constructor of class A | +| tsTest.ts:1:1:13:0 | exports object of module tsTest | +| tsTest.ts:1:1:13:0 | module object of module tsTest | +| tsTest.ts:8:1:10:1 | function setX | +| tsTest.ts:8:1:10:1 | instance of function setX | | tst2.js:3:2:5:1 | anonymous function | | tst2.js:3:2:5:1 | instance of anonymous function | | tst.js:1:1:39:1 | arguments object of function tst | @@ -341,9 +345,5 @@ | tst.js:174:1:183:1 | function awaitFlow | | tst.mjs:1:1:4:0 | exports object of module tst | | tst.mjs:1:1:4:0 | module object of module tst | -| tst.ts:1:1:13:0 | exports object of module tst | -| tst.ts:1:1:13:0 | module object of module tst | -| tst.ts:8:1:10:1 | function setX | -| tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | function f | | with.js:1:1:17:1 | instance of function f | diff --git a/javascript/ql/test/library-tests/Flow/abseval.expected b/javascript/ql/test/library-tests/Flow/abseval.expected index ff2ad70cdd4..ba021a2d36b 100644 --- a/javascript/ql/test/library-tests/Flow/abseval.expected +++ b/javascript/ql/test/library-tests/Flow/abseval.expected @@ -281,6 +281,10 @@ | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | "" | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | non-empty, non-numeric string | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | file://:0:0:0:0 | numeric string | +| tsTest.ts:2:14:2:14 | x | tsTest.ts:2:18:2:19 | 42 | file://:0:0:0:0 | non-zero value | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | file://:0:0:0:0 | indefinite value (namespace) | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | file://:0:0:0:0 | non-zero value | +| tsTest.ts:12:5:12:5 | a | tsTest.ts:12:9:12:9 | A | file://:0:0:0:0 | object | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | file://:0:0:0:0 | "" | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | file://:0:0:0:0 | indefinite value (global) | | tst.js:3:7:3:8 | x1 | tst.js:3:12:3:15 | true | file://:0:0:0:0 | true | @@ -462,10 +466,6 @@ | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | file://:0:0:0:0 | indefinite value (global) | | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | file://:0:0:0:0 | indefinite value (heap) | | tst.mjs:3:5:3:7 | req | tst.mjs:3:11:3:17 | require | file://:0:0:0:0 | indefinite value (global) | -| tst.ts:2:14:2:14 | x | tst.ts:2:18:2:19 | 42 | file://:0:0:0:0 | non-zero value | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | file://:0:0:0:0 | indefinite value (namespace) | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | file://:0:0:0:0 | non-zero value | -| tst.ts:12:5:12:5 | a | tst.ts:12:9:12:9 | A | file://:0:0:0:0 | object | | with.js:2:7:2:7 | x | with.js:2:11:2:12 | 42 | file://:0:0:0:0 | non-zero value | | with.js:2:15:2:15 | y | with.js:2:19:2:22 | null | file://:0:0:0:0 | null | | with.js:4:9:4:10 | r1 | with.js:4:14:4:14 | x | file://:0:0:0:0 | indefinite value (eval) | diff --git a/javascript/ql/test/library-tests/Flow/getAPrototype.expected b/javascript/ql/test/library-tests/Flow/getAPrototype.expected index 07ff1f76b24..438fb61fa2c 100644 --- a/javascript/ql/test/library-tests/Flow/getAPrototype.expected +++ b/javascript/ql/test/library-tests/Flow/getAPrototype.expected @@ -58,6 +58,7 @@ | refinements.js:44:3:48:3 | instance of function inner | refinements.js:44:3:48:3 | instance of function inner | | refinements.js:58:1:62:1 | instance of function f6 | refinements.js:58:1:62:1 | instance of function f6 | | ts2.ts:1:10:1:22 | instance of anonymous function | ts2.ts:1:10:1:22 | instance of anonymous function | +| tsTest.ts:8:1:10:1 | instance of function setX | tsTest.ts:8:1:10:1 | instance of function setX | | tst2.js:3:2:5:1 | instance of anonymous function | tst2.js:3:2:5:1 | instance of anonymous function | | tst.js:1:1:39:1 | instance of function tst | tst.js:1:1:39:1 | instance of function tst | | tst.js:15:12:15:23 | instance of function xd | tst.js:15:12:15:23 | instance of function xd | @@ -88,5 +89,4 @@ | tst.js:144:1:149:1 | instance of function tst3 | tst.js:144:1:149:1 | instance of function tst3 | | tst.js:151:1:162:1 | instance of function tst4 | tst.js:151:1:162:1 | instance of function tst4 | | tst.js:164:1:172:1 | instance of function tst5 | tst.js:164:1:172:1 | instance of function tst5 | -| tst.ts:8:1:10:1 | instance of function setX | tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | instance of function f | with.js:1:1:17:1 | instance of function f | diff --git a/javascript/ql/test/library-tests/Flow/tst.ts b/javascript/ql/test/library-tests/Flow/tsTest.ts similarity index 100% rename from javascript/ql/test/library-tests/Flow/tst.ts rename to javascript/ql/test/library-tests/Flow/tsTest.ts diff --git a/javascript/ql/test/library-tests/Flow/types.expected b/javascript/ql/test/library-tests/Flow/types.expected index 9b13b469bed..1cc6a526382 100644 --- a/javascript/ql/test/library-tests/Flow/types.expected +++ b/javascript/ql/test/library-tests/Flow/types.expected @@ -156,6 +156,9 @@ | refinements.js:53:7:53:8 | x5 | refinements.js:53:12:53:12 | f | undefined | | refinements.js:55:7:55:8 | x6 | refinements.js:55:12:55:12 | f | null or undefined | | refinements.js:61:7:61:8 | x2 | refinements.js:61:12:61:12 | x | string | +| tsTest.ts:2:14:2:14 | x | tsTest.ts:2:18:2:19 | 42 | number | +| tsTest.ts:4:7:4:8 | x2 | tsTest.ts:4:12:4:12 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | +| tsTest.ts:12:5:12:5 | a | tsTest.ts:12:9:12:9 | A | object | | tst2.js:4:7:4:7 | x | tst2.js:4:11:4:20 | someGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined | | tst.js:3:7:3:8 | x1 | tst.js:3:12:3:15 | true | boolean | | tst.js:4:7:4:8 | x2 | tst.js:4:12:4:16 | false | boolean | @@ -239,9 +242,6 @@ | tst.js:185:5:185:21 | [someOtherGlobal] | tst.js:185:25:185:26 | [] | object | | tst.js:186:5:186:6 | x1 | tst.js:186:10:186:24 | someOtherGlobal | boolean, class, date, function, null, number, object, regular expression,string or undefined | | tst.mjs:3:5:3:7 | req | tst.mjs:3:11:3:17 | require | boolean, class, date, function, null, number, object, regular expression,string or undefined | -| tst.ts:2:14:2:14 | x | tst.ts:2:18:2:19 | 42 | number | -| tst.ts:4:7:4:8 | x2 | tst.ts:4:12:4:12 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | -| tst.ts:12:5:12:5 | a | tst.ts:12:9:12:9 | A | object | | with.js:2:7:2:7 | x | with.js:2:11:2:12 | 42 | number | | with.js:2:15:2:15 | y | with.js:2:19:2:22 | null | null | | with.js:4:9:4:10 | r1 | with.js:4:14:4:14 | x | boolean, class, date, function, null, number, object, regular expression,string or undefined | diff --git a/javascript/ql/test/library-tests/LocalObjects/tst.ts b/javascript/ql/test/library-tests/LocalObjects/tst2.ts similarity index 100% rename from javascript/ql/test/library-tests/LocalObjects/tst.ts rename to javascript/ql/test/library-tests/LocalObjects/tst2.ts diff --git a/javascript/ql/test/library-tests/NPM/Modules.expected b/javascript/ql/test/library-tests/NPM/Modules.expected index 9ce1e5fccd6..89712d4df84 100644 --- a/javascript/ql/test/library-tests/NPM/Modules.expected +++ b/javascript/ql/test/library-tests/NPM/Modules.expected @@ -1,5 +1,5 @@ | b | src/node_modules/b/lib/index.js:1:1:2:0 | | -| b | src/node_modules/b/lib/index.ts:1:1:2:0 | | +| b | src/node_modules/b/lib/util.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | | d | src/node_modules/d/main.js:1:1:2:0 | | | test-package | src/index.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected index c8fe4a8ba4b..deb13a53a50 100644 --- a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected +++ b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected @@ -1,4 +1,4 @@ -| b | src/node_modules/b/lib/index.ts:1:1:2:0 | | +| b | src/node_modules/b/lib/index.js:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | | d | src/node_modules/d/main.js:1:1:2:0 | | | test-package | src/index.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/index.ts b/javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/util.ts similarity index 100% rename from javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/index.ts rename to javascript/ql/test/library-tests/NPM/src/node_modules/b/lib/util.ts diff --git a/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected b/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected index 1c1f14deabe..ac5e94c543d 100644 --- a/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected +++ b/javascript/ql/test/library-tests/Promises/AdditionalPromises.expected @@ -77,3 +77,4 @@ | promises.js:62:19:62:41 | Promise ... source) | | promises.js:71:5:71:27 | Promise ... source) | | promises.js:72:5:72:41 | new Pro ... ource)) | +| promises.js:79:19:79:41 | Promise ... source) | diff --git a/javascript/ql/test/library-tests/Promises/flow.qll b/javascript/ql/test/library-tests/Promises/flow.qll index 0b99ee9bcbd..94c2af70674 100644 --- a/javascript/ql/test/library-tests/Promises/flow.qll +++ b/javascript/ql/test/library-tests/Promises/flow.qll @@ -1,4 +1,5 @@ import javascript +private import semmle.javascript.dataflow.internal.StepSummary class Configuration extends DataFlow::Configuration { Configuration() { this = "PromiseDataFlowFlowTestingConfig" } @@ -32,3 +33,7 @@ query predicate exclusiveTaintFlow(DataFlow::Node source, DataFlow::Node sink) { not any(Configuration c).hasFlow(source, sink) and any(TaintConfig c).hasFlow(source, sink) } + +query predicate typetrack(DataFlow::SourceNode succ, DataFlow::SourceNode pred, StepSummary summary) { + succ = PromiseTypeTracking::promiseStep(pred, summary) +} diff --git a/javascript/ql/test/library-tests/Promises/promises.js b/javascript/ql/test/library-tests/Promises/promises.js index f053c81a9a9..8a3d0cbc5cf 100644 --- a/javascript/ql/test/library-tests/Promises/promises.js +++ b/javascript/ql/test/library-tests/Promises/promises.js @@ -74,3 +74,10 @@ resolver.resolve(source); resolver.promise.then(val => { var sink = val }); })(); + +(function(source) { + var promise = Promise.resolve(source); + promise.then(function (val) { + var sink = val; + }); +})(); \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Promises/tests.expected b/javascript/ql/test/library-tests/Promises/tests.expected index f4ee1263be5..44dfa0d22e2 100644 --- a/javascript/ql/test/library-tests/Promises/tests.expected +++ b/javascript/ql/test/library-tests/Promises/tests.expected @@ -19,6 +19,7 @@ test_ResolvedPromiseDefinition | promises.js:53:19:53:41 | Promise ... source) | promises.js:53:35:53:40 | source | | promises.js:62:19:62:41 | Promise ... source) | promises.js:62:35:62:40 | source | | promises.js:71:5:71:27 | Promise ... source) | promises.js:71:21:71:26 | source | +| promises.js:79:19:79:41 | Promise ... source) | promises.js:79:35:79:40 | source | test_PromiseDefinition_getARejectHandler | flow.js:26:2:26:49 | new Pro ... ource)) | flow.js:26:69:26:80 | y => sink(y) | | flow.js:32:2:32:49 | new Pro ... ource)) | flow.js:32:57:32:68 | x => sink(x) | @@ -220,3 +221,137 @@ flow | flow.js:2:15:2:22 | "source" | flow.js:131:43:131:43 | x | exclusiveTaintFlow | interflow.js:3:18:3:25 | "source" | interflow.js:18:10:18:14 | error | +typetrack +| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | in $PromiseResolveField$ | +| flow.js:20:2:20:43 | Promise ... ink(x)) | flow.js:20:36:20:42 | sink(x) | store $PromiseResolveField$ | +| flow.js:20:31:20:31 | x | flow.js:20:2:20:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | in $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:36:22:41 | foo(x) | store $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | in $PromiseResolveField$ | +| flow.js:22:2:22:56 | Promise ... ink(y)) | flow.js:22:49:22:55 | sink(y) | store $PromiseResolveField$ | +| flow.js:22:31:22:31 | x | flow.js:22:2:22:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | in $PromiseResolveField$ | +| flow.js:24:2:24:68 | new Pro ... ink(x)) | flow.js:24:61:24:67 | sink(x) | store $PromiseResolveField$ | +| flow.js:24:56:24:56 | x | flow.js:24:2:24:49 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | in $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:61:26:66 | foo(x) | store $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | in $PromiseResolveField$ | +| flow.js:26:2:26:81 | new Pro ... ink(y)) | flow.js:26:74:26:80 | sink(y) | store $PromiseResolveField$ | +| flow.js:26:56:26:56 | x | flow.js:26:2:26:49 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | in $PromiseResolveField$ | +| flow.js:28:2:28:60 | Promise ... ink(z)) | flow.js:28:53:28:59 | sink(z) | store $PromiseResolveField$ | +| flow.js:28:30:28:30 | x | flow.js:28:2:28:23 | Promise ... ("foo") | load $PromiseResolveField$ | +| flow.js:28:48:28:48 | z | flow.js:28:2:28:41 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | in $PromiseResolveField$ | +| flow.js:30:2:30:60 | Promise ... ink(z)) | flow.js:30:53:30:59 | sink(z) | store $PromiseResolveField$ | +| flow.js:30:31:30:31 | x | flow.js:30:2:30:24 | Promise ... source) | load $PromiseResolveField$ | +| flow.js:30:48:30:48 | z | flow.js:30:2:30:41 | Promise ... "foo") | load $PromiseResolveField$ | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:2:32:49 | new Pro ... ource)) | in $PromiseResolveField$ | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | in $PromiseResolveField$ | +| flow.js:32:2:32:69 | new Pro ... ink(x)) | flow.js:32:62:32:68 | sink(x) | store $PromiseResolveField$ | +| flow.js:34:2:34:41 | Promise ... => { }) | flow.js:34:2:34:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | in $PromiseResolveField$ | +| flow.js:34:2:34:60 | Promise ... ink(a)) | flow.js:34:53:34:59 | sink(a) | store $PromiseResolveField$ | +| flow.js:34:48:34:48 | a | flow.js:34:2:34:41 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:37:11:37:29 | p5.catch(() => { }) | flow.js:36:11:36:33 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | in $PromiseResolveField$ | +| flow.js:38:11:38:31 | p6.then ... ink(a)) | flow.js:38:24:38:30 | sink(a) | store $PromiseResolveField$ | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:2:40:65 | new Pro ... => { }) | in $PromiseResolveField$ | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | in $PromiseResolveField$ | +| flow.js:40:2:40:85 | new Pro ... ink(x)) | flow.js:40:78:40:84 | sink(x) | store $PromiseResolveField$ | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:2:42:76 | new Pro ... => { }) | in $PromiseResolveField$ | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | in $PromiseResolveField$ | +| flow.js:42:2:42:96 | new Pro ... ink(x)) | flow.js:42:89:42:95 | sink(x) | store $PromiseResolveField$ | +| flow.js:44:2:44:41 | Promise ... => { }) | flow.js:44:2:44:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:44:2:44:58 | Promise ... => { }) | flow.js:44:2:44:41 | Promise ... => { }) | in $PromiseResolveField$ | +| flow.js:44:2:44:75 | Promise ... => { }) | flow.js:44:2:44:58 | Promise ... => { }) | in $PromiseResolveField$ | +| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | in $PromiseResolveField$ | +| flow.js:44:2:44:94 | Promise ... ink(a)) | flow.js:44:87:44:93 | sink(a) | store $PromiseResolveField$ | +| flow.js:44:82:44:82 | a | flow.js:44:2:44:75 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:46:2:46:43 | Promise ... => { }) | flow.js:46:2:46:24 | Promise ... source) | in $PromiseResolveField$ | +| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | in $PromiseResolveField$ | +| flow.js:46:2:46:62 | Promise ... ink(a)) | flow.js:46:55:46:61 | sink(a) | store $PromiseResolveField$ | +| flow.js:46:50:46:50 | a | flow.js:46:2:46:43 | Promise ... => { }) | load $PromiseResolveField$ | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:2:48:36 | new Pro ... urce }) | in $PromiseResolveField$ | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | in $PromiseResolveField$ | +| flow.js:48:2:48:56 | new Pro ... ink(x)) | flow.js:48:49:48:55 | sink(x) | store $PromiseResolveField$ | +| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | in $PromiseResolveField$ | +| flow.js:53:2:53:41 | createP ... ink(v)) | flow.js:53:34:53:40 | sink(v) | store $PromiseResolveField$ | +| flow.js:53:29:53:29 | v | flow.js:53:2:53:22 | createP ... source) | load $PromiseResolveField$ | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:57:12:57:31 | p9.finally(() => {}) | in $PromiseResolveField$ | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | in $PromiseResolveField$ | +| flow.js:58:2:58:26 | p10.cat ... ink(x)) | flow.js:58:19:58:25 | sink(x) | store $PromiseResolveField$ | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:61:12:61:29 | p11.then(() => {}) | in $PromiseResolveField$ | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | in $PromiseResolveField$ | +| flow.js:62:2:62:24 | p12.cat ... ink(x)) | flow.js:62:17:62:23 | sink(x) | store $PromiseResolveField$ | +| flow.js:65:3:65:56 | await n ... ource)) | flow.js:65:9:65:56 | new Pro ... ource)) | load $PromiseResolveField$ | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:2:76:32 | chained ... => {}) | in $PromiseResolveField$ | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | in $PromiseResolveField$ | +| flow.js:76:2:76:52 | chained ... ink(e)) | flow.js:76:45:76:51 | sink(e) | store $PromiseResolveField$ | +| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | in $PromiseResolveField$ | +| flow.js:79:3:79:22 | p.then(x => sink(x)) | flow.js:79:15:79:21 | sink(x) | store $PromiseResolveField$ | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:83:32:83:32 | p | in $PromiseResolveField$ | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | in $PromiseResolveField$ | +| flow.js:84:3:84:23 | p.catch ... ink(e)) | flow.js:84:16:84:22 | sink(e) | store $PromiseResolveField$ | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:3:89:27 | ("foo", ... => {}) | in $PromiseResolveField$ | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | in $PromiseResolveField$ | +| flow.js:89:3:89:47 | ("foo", ... ink(e)) | flow.js:89:40:89:46 | sink(e) | store $PromiseResolveField$ | +| flow.js:103:2:103:76 | new Pro ... ource}) | flow.js:103:2:103:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | in $PromiseResolveField$ | +| flow.js:103:2:103:95 | new Pro ... ink(x)) | flow.js:103:88:103:94 | sink(x) | store $PromiseResolveField$ | +| flow.js:103:83:103:83 | x | flow.js:103:2:103:76 | new Pro ... ource}) | load $PromiseResolveField$ | +| flow.js:105:2:105:77 | new Pro ... ource}) | flow.js:105:2:105:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:2:105:77 | new Pro ... ource}) | in $PromiseResolveField$ | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | in $PromiseResolveField$ | +| flow.js:105:2:105:97 | new Pro ... ink(x)) | flow.js:105:90:105:96 | sink(x) | store $PromiseResolveField$ | +| flow.js:109:2:109:71 | new Pro ... jected) | flow.js:109:2:109:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:2:109:71 | new Pro ... jected) | in $PromiseResolveField$ | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | in $PromiseResolveField$ | +| flow.js:109:2:109:91 | new Pro ... ink(x)) | flow.js:109:84:109:90 | sink(x) | store $PromiseResolveField$ | +| flow.js:111:2:111:69 | new Pro ... jected) | flow.js:111:2:111:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | in $PromiseResolveField$ | +| flow.js:111:2:111:88 | new Pro ... ink(x)) | flow.js:111:81:111:87 | sink(x) | store $PromiseResolveField$ | +| flow.js:111:76:111:76 | x | flow.js:111:2:111:69 | new Pro ... jected) | load $PromiseResolveField$ | +| flow.js:113:2:113:69 | new Pro ... jected) | flow.js:113:2:113:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:2:113:69 | new Pro ... jected) | in $PromiseResolveField$ | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | in $PromiseResolveField$ | +| flow.js:113:2:113:89 | new Pro ... ink(x)) | flow.js:113:82:113:88 | sink(x) | store $PromiseResolveField$ | +| flow.js:117:2:117:69 | new Pro ... solved) | flow.js:117:2:117:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:2:117:69 | new Pro ... solved) | in $PromiseResolveField$ | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | in $PromiseResolveField$ | +| flow.js:117:2:117:89 | new Pro ... ink(x)) | flow.js:117:82:117:88 | sink(x) | store $PromiseResolveField$ | +| flow.js:119:2:119:69 | new Pro ... solved) | flow.js:119:2:119:48 | new Pro ... "BLA")) | in $PromiseResolveField$ | +| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | in $PromiseResolveField$ | +| flow.js:119:2:119:88 | new Pro ... ink(x)) | flow.js:119:81:119:87 | sink(x) | store $PromiseResolveField$ | +| flow.js:119:76:119:76 | x | flow.js:119:2:119:69 | new Pro ... solved) | load $PromiseResolveField$ | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:2:121:41 | Promise ... solved) | in $PromiseResolveField$ | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | in $PromiseResolveField$ | +| flow.js:121:2:121:61 | Promise ... ink(x)) | flow.js:121:54:121:60 | sink(x) | store $PromiseResolveField$ | +| flow.js:121:28:121:28 | x | flow.js:121:2:121:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | in $PromiseResolveField$ | +| flow.js:123:2:123:60 | Promise ... ink(x)) | flow.js:123:53:123:59 | sink(x) | store $PromiseResolveField$ | +| flow.js:123:28:123:28 | x | flow.js:123:2:123:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:123:48:123:48 | x | flow.js:123:2:123:41 | Promise ... solved) | load $PromiseResolveField$ | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:2:125:41 | Promise ... jected) | in $PromiseResolveField$ | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | in $PromiseResolveField$ | +| flow.js:125:2:125:61 | Promise ... ink(x)) | flow.js:125:54:125:60 | sink(x) | store $PromiseResolveField$ | +| flow.js:125:28:125:28 | x | flow.js:125:2:125:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | in $PromiseResolveField$ | +| flow.js:127:2:127:60 | Promise ... ink(x)) | flow.js:127:53:127:59 | sink(x) | store $PromiseResolveField$ | +| flow.js:127:28:127:28 | x | flow.js:127:2:127:21 | Promise.resolve(123) | load $PromiseResolveField$ | +| flow.js:127:48:127:48 | x | flow.js:127:2:127:41 | Promise ... jected) | load $PromiseResolveField$ | +| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | in $PromiseResolveField$ | +| flow.js:129:2:129:71 | new Pro ... ink(x)) | flow.js:129:64:129:70 | sink(x) | store $PromiseResolveField$ | +| flow.js:129:59:129:59 | x | flow.js:129:2:129:52 | new Pro ... olved)) | load $PromiseResolveField$ | +| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | in $PromiseResolveField$ | +| flow.js:131:2:131:45 | Promise ... ink(x)) | flow.js:131:38:131:44 | sink(x) | store $PromiseResolveField$ | +| flow.js:131:33:131:33 | x | flow.js:131:2:131:26 | Promise ... solved) | load $PromiseResolveField$ | +| interflow.js:6:3:9:23 | loadScr ... eError) | interflow.js:6:3:8:26 | loadScr ... () { }) | in $PromiseResolveField$ | +| promises.js:23:3:25:4 | promise ... v;\\n }) | promises.js:10:18:17:4 | new Pro ... );\\n }) | in $PromiseResolveField$ | +| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | in $PromiseResolveField$ | +| promises.js:33:19:35:6 | new Pro ... \\n }) | promises.js:34:17:34:22 | source | store $PromiseResolveField$ | +| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | in $PromiseResolveField$ | +| promises.js:43:19:45:6 | Q.Promi ... \\n }) | promises.js:44:17:44:22 | source | store $PromiseResolveField$ | +| promises.js:71:34:71:36 | val | promises.js:71:5:71:27 | Promise ... source) | load $PromiseResolveField$ | +| promises.js:72:48:72:50 | val | promises.js:72:5:72:41 | new Pro ... ource)) | load $PromiseResolveField$ | +| promises.js:75:27:75:29 | val | promises.js:75:5:75:20 | resolver.promise | load $PromiseResolveField$ | diff --git a/javascript/ql/test/library-tests/RangeAnalysis/constants.js b/javascript/ql/test/library-tests/RangeAnalysis/constants.js index 9e1a3b914e3..decd2a19e9a 100644 --- a/javascript/ql/test/library-tests/RangeAnalysis/constants.js +++ b/javascript/ql/test/library-tests/RangeAnalysis/constants.js @@ -6,3 +6,8 @@ function f() { if (two > one) {} // NOT OK - always true if (two <= one) {} // NOT OK - always false } + +function underscores(x) { + if (x >= 1_000_000) return; // OK + if (x >= 1_000) return; // OK +} diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected new file mode 100644 index 00000000000..59f6fd6e79b --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.expected @@ -0,0 +1 @@ +| Success | diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql new file mode 100644 index 00000000000..9a5350948fe --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql @@ -0,0 +1,16 @@ +/** + * Test that fails to compile if the domain of `SourceNode` depends on `SourceNode.flowsTo` (recursively). + * + * This tests adds a negative dependency `flowsTo --!--> SourceNode` + * so that the undesired edge `SourceNode --> flowsTo` completes a negative cycle. + */ + +import javascript + +class BadSourceNode extends DataFlow::SourceNode { + BadSourceNode() { this.(DataFlow::PropRead).getPropertyName() = "foo" } + + override predicate flowsTo(DataFlow::Node node) { not node instanceof DataFlow::SourceNode } +} + +select "Success" diff --git a/javascript/ql/test/library-tests/RecursionPrevention/tst.js b/javascript/ql/test/library-tests/RecursionPrevention/tst.js new file mode 100644 index 00000000000..d5a82a682bc --- /dev/null +++ b/javascript/ql/test/library-tests/RecursionPrevention/tst.js @@ -0,0 +1,2 @@ +// The contents of this file don't matter +let x = 1; diff --git a/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected b/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected index fcb1b6cbba0..6673b6e7cb3 100644 --- a/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected +++ b/javascript/ql/test/library-tests/Refinements/Refinement_getRefinedVar.expected @@ -1,2 +1,2 @@ -| tst.js:4:3:4:27 | (typeof ... nction' | x | -| tst.js:8:3:8:23 | (typeof ... === 'u' | x | +| tst.js:4:3:4:27 | (typeof ... nction' | tst.js:3:12:3:12 | x | +| tst.js:8:3:8:23 | (typeof ... === 'u' | tst.js:3:12:3:12 | x | diff --git a/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected b/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected index 7f37d2d2a11..e971020cdd6 100644 --- a/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected +++ b/javascript/ql/test/library-tests/SSA/GetRhsNode/GetRhsNode.expected @@ -1,14 +1,14 @@ -| tst.js:2:7:2:13 | a = g() | a | tst.js:2:11:2:13 | g() | -| tst.js:4:7:4:24 | { propB: b } = g() | b | tst.js:4:9:4:16 | propB: b | -| tst.js:6:7:6:34 | { propC ... } = g() | c | tst.js:6:9:6:16 | propC: c | -| tst.js:6:7:6:34 | { propC ... } = g() | d | tst.js:6:19:6:26 | propD: d | -| tst.js:8:7:8:41 | { array ... } = g() | elm1 | tst.js:8:22:8:25 | elm1 | -| tst.js:8:7:8:41 | { array ... } = g() | elm2 | tst.js:8:28:8:31 | elm2 | -| tst.js:17:3:17:22 | ({ propB: b }) = g() | b | tst.js:17:6:17:13 | propB: b | -| tst.js:19:3:19:32 | ({ prop ... ) = g() | c | tst.js:19:6:19:13 | propC: c | -| tst.js:19:3:19:32 | ({ prop ... ) = g() | d | tst.js:19:16:19:23 | propD: d | -| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm1 | tst.js:21:5:21:8 | elm1 | -| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | elm2 | tst.js:21:11:21:14 | elm2 | -| tst.js:31:12:31:23 | [elm1, elm2] | elm1 | tst.js:31:13:31:16 | elm1 | -| tst.js:31:12:31:23 | [elm1, elm2] | elm2 | tst.js:31:19:31:22 | elm2 | -| tst.js:31:26:31:40 | { prop: value } | value | tst.js:31:28:31:38 | prop: value | +| tst.js:2:7:2:13 | a = g() | tst.js:2:7:2:7 | a | tst.js:2:11:2:13 | g() | +| tst.js:4:7:4:24 | { propB: b } = g() | tst.js:4:16:4:16 | b | tst.js:4:9:4:16 | propB: b | +| tst.js:6:7:6:34 | { propC ... } = g() | tst.js:6:16:6:16 | c | tst.js:6:9:6:16 | propC: c | +| tst.js:6:7:6:34 | { propC ... } = g() | tst.js:6:26:6:26 | d | tst.js:6:19:6:26 | propD: d | +| tst.js:8:7:8:41 | { array ... } = g() | tst.js:8:22:8:25 | elm1 | tst.js:8:22:8:25 | elm1 | +| tst.js:8:7:8:41 | { array ... } = g() | tst.js:8:28:8:31 | elm2 | tst.js:8:28:8:31 | elm2 | +| tst.js:17:3:17:22 | ({ propB: b }) = g() | tst.js:4:16:4:16 | b | tst.js:17:6:17:13 | propB: b | +| tst.js:19:3:19:32 | ({ prop ... ) = g() | tst.js:6:16:6:16 | c | tst.js:19:6:19:13 | propC: c | +| tst.js:19:3:19:32 | ({ prop ... ) = g() | tst.js:6:26:6:26 | d | tst.js:19:16:19:23 | propD: d | +| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | tst.js:8:22:8:25 | elm1 | tst.js:21:5:21:8 | elm1 | +| tst.js:21:3:21:22 | [ elm1, elm2 ] = g() | tst.js:8:28:8:31 | elm2 | tst.js:21:11:21:14 | elm2 | +| tst.js:31:12:31:23 | [elm1, elm2] | tst.js:31:13:31:16 | elm1 | tst.js:31:13:31:16 | elm1 | +| tst.js:31:12:31:23 | [elm1, elm2] | tst.js:31:19:31:22 | elm2 | tst.js:31:19:31:22 | elm2 | +| tst.js:31:26:31:40 | { prop: value } | tst.js:31:34:31:38 | value | tst.js:31:28:31:38 | prop: value | diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js new file mode 100644 index 00000000000..80f511a99af --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.js @@ -0,0 +1 @@ +export default 45; diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts new file mode 100644 index 00000000000..66ea6d25d40 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/index.ts @@ -0,0 +1 @@ +export default 45 as number; diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected new file mode 100644 index 00000000000..5cd97cf9527 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.expected @@ -0,0 +1 @@ +| index.ts:0:0:0:0 | index.ts | diff --git a/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql new file mode 100644 index 00000000000..ff70967ddac --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/CompiledOutput/test.ql @@ -0,0 +1,3 @@ +import javascript + +query File files() { any() } diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected b/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected index bb82e314424..08ec97d5a9d 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/modules/ModuleRef.expected @@ -1,12 +1,12 @@ -| cm1 | -| cm2 | -| cm3 | -| cm4 | -| cm5 | -| cm6 | -| cm7 | -| cm8 | -| dm1 | -| m | -| mcm1 | -| rm1 | +| module-refs.js:3:9:3:11 | dm1 | +| module-refs.js:6:9:6:11 | rm1 | +| module-refs.js:9:9:9:11 | cm1 | +| module-refs.js:10:9:10:11 | cm2 | +| module-refs.js:11:9:11:11 | cm3 | +| module-refs.js:12:9:12:11 | cm4 | +| module-refs.js:13:9:13:11 | cm5 | +| module-refs.js:14:9:14:11 | cm6 | +| module-refs.js:15:9:15:11 | cm7 | +| module-refs.js:16:9:16:11 | cm8 | +| module-refs.js:22:9:22:12 | mcm1 | +| tst.js:19:7:19:7 | m | diff --git a/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected b/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected index be5f2b10245..592ec644363 100644 --- a/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected +++ b/javascript/ql/test/library-tests/frameworks/Concepts/FileNameSource.expected @@ -27,3 +27,4 @@ | tst-file-names.js:45:12:45:42 | globule ... /*.js") | | tst-file-names.js:46:12:46:51 | globule ... .js"]}) | | tst-file-names.js:47:12:47:52 | globule ... b.js"]) | +| tst-file-names.js:51:15:51:23 | await foo | diff --git a/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js b/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js index 2892a82d515..7c9670dba04 100644 --- a/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js +++ b/javascript/ql/test/library-tests/frameworks/Concepts/tst-file-names.js @@ -45,3 +45,8 @@ var bool = globule.isMatch('**/*.js', ["foo.js"]) var map1 = globule.findMapping("foo/*.js") var map2 = globule.mapping({src: ["a.js", "b.js"]}) var map3 = globule.mapping(["foo/a.js", "foo/b.js"]) + +async function bar() { + var foo = globby(_); + var files = await foo; +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected b/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected index 417b6f66ab0..6e6606a6bec 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected +++ b/javascript/ql/test/library-tests/frameworks/Electron/BrowserObject.expected @@ -1,5 +1,3 @@ -| electron.d.ts:2:16:2:28 | BrowserWindow | -| electron.d.ts:3:16:3:26 | BrowserView | | electron.js:3:5:3:48 | bw | | electron.js:3:10:3:48 | new Bro ... s: {}}) | | electron.js:4:5:4:46 | bv | @@ -14,7 +12,9 @@ | electron.js:62:13:62:59 | new Bro ... 1500 }) | | electron.js:63:3:63:5 | win | | electron.js:65:18:65:20 | win | -| electron.ts:3:12:3:13 | bw | -| electron.ts:3:40:3:41 | bv | -| electron.ts:4:3:4:4 | bw | -| electron.ts:5:3:5:4 | bv | +| electronTs.d.ts:2:16:2:28 | BrowserWindow | +| electronTs.d.ts:3:16:3:26 | BrowserView | +| electronTs.ts:3:12:3:13 | bw | +| electronTs.ts:3:40:3:41 | bv | +| electronTs.ts:4:3:4:4 | bw | +| electronTs.ts:5:3:5:4 | bv | diff --git a/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected b/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected index a57fb6648fb..d40ce11bdb4 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected +++ b/javascript/ql/test/library-tests/frameworks/Electron/WebContents.expected @@ -1,5 +1,5 @@ | electron.js:39:1:39:19 | foo(bw).webContents | | electron.js:40:1:40:19 | foo(bv).webContents | | electron.js:65:18:65:32 | win.webContents | -| electron.ts:4:3:4:16 | bw.webContents | -| electron.ts:5:3:5:16 | bv.webContents | +| electronTs.ts:4:3:4:16 | bw.webContents | +| electronTs.ts:5:3:5:16 | bv.webContents | diff --git a/javascript/ql/test/library-tests/frameworks/Electron/electron.d.ts b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.d.ts similarity index 100% rename from javascript/ql/test/library-tests/frameworks/Electron/electron.d.ts rename to javascript/ql/test/library-tests/frameworks/Electron/electronTs.d.ts diff --git a/javascript/ql/test/library-tests/frameworks/Electron/electron.ts b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts similarity index 72% rename from javascript/ql/test/library-tests/frameworks/Electron/electron.ts rename to javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts index a4fcd1f530f..a06802db62c 100644 --- a/javascript/ql/test/library-tests/frameworks/Electron/electron.ts +++ b/javascript/ql/test/library-tests/frameworks/Electron/electronTs.ts @@ -1,4 +1,4 @@ -/// +/// function f(bw: Electron.BrowserWindow, bv: Electron.BrowserView) { bw.webContents; diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected index 6232c852ab6..112a72c7762 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics.expected @@ -1,4 +1,4 @@ | tst2.js:0:0:0:0 | tst2.js | +| tst3.ts:0:0:0:0 | tst3.ts | | tst.html:0:0:0:0 | tst.html | | tst.js:0:0:0:0 | tst.js | -| tst.ts:0:0:0:0 | tst.ts | diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected index afed63c473b..e21fbbc260f 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_length.expected @@ -1,4 +1,4 @@ | tst2.js:0:0:0:0 | tst2.js | 26 | +| tst3.ts:0:0:0:0 | tst3.ts | 31 | | tst.html:0:0:0:0 | tst.html | 127 | | tst.js:0:0:0:0 | tst.js | 26 | -| tst.ts:0:0:0:0 | tst.ts | 31 | diff --git a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected index 53266032907..003026d73ec 100644 --- a/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected +++ b/javascript/ql/test/library-tests/meta/Extraction/FileWithExtractionMetrics_phases.expected @@ -7,6 +7,15 @@ | tst2.js:0:0:0:0 | tst2.js | LexicalExtractor_extractTokens | | tst2.js:0:0:0:0 | tst2.js | TypeScriptASTConverter_convertAST | | tst2.js:0:0:0:0 | tst2.js | TypeScriptParser_talkToParserWrapper | +| tst3.ts:0:0:0:0 | tst3.ts | ASTExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | CFGExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | FileExtractor_extractContents | +| tst3.ts:0:0:0:0 | tst3.ts | JSExtractor_extract | +| tst3.ts:0:0:0:0 | tst3.ts | JSParser_parse | +| tst3.ts:0:0:0:0 | tst3.ts | LexicalExtractor_extractLines | +| tst3.ts:0:0:0:0 | tst3.ts | LexicalExtractor_extractTokens | +| tst3.ts:0:0:0:0 | tst3.ts | TypeScriptASTConverter_convertAST | +| tst3.ts:0:0:0:0 | tst3.ts | TypeScriptParser_talkToParserWrapper | | tst.html:0:0:0:0 | tst.html | ASTExtractor_extract | | tst.html:0:0:0:0 | tst.html | CFGExtractor_extract | | tst.html:0:0:0:0 | tst.html | FileExtractor_extractContents | @@ -25,12 +34,3 @@ | tst.js:0:0:0:0 | tst.js | LexicalExtractor_extractTokens | | tst.js:0:0:0:0 | tst.js | TypeScriptASTConverter_convertAST | | tst.js:0:0:0:0 | tst.js | TypeScriptParser_talkToParserWrapper | -| tst.ts:0:0:0:0 | tst.ts | ASTExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | CFGExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | FileExtractor_extractContents | -| tst.ts:0:0:0:0 | tst.ts | JSExtractor_extract | -| tst.ts:0:0:0:0 | tst.ts | JSParser_parse | -| tst.ts:0:0:0:0 | tst.ts | LexicalExtractor_extractLines | -| tst.ts:0:0:0:0 | tst.ts | LexicalExtractor_extractTokens | -| tst.ts:0:0:0:0 | tst.ts | TypeScriptASTConverter_convertAST | -| tst.ts:0:0:0:0 | tst.ts | TypeScriptParser_talkToParserWrapper | diff --git a/javascript/ql/test/library-tests/meta/Extraction/tst.ts b/javascript/ql/test/library-tests/meta/Extraction/tst3.ts similarity index 100% rename from javascript/ql/test/library-tests/meta/Extraction/tst.ts rename to javascript/ql/test/library-tests/meta/Extraction/tst3.ts diff --git a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected index bf97e07b559..b9013913d10 100644 --- a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected +++ b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected @@ -1,46 +1,46 @@ -| arguments | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| arguments | assignments.js:3:1:6:1 | functio ... = 56;\\n} | -| arguments | assignments.js:4:10:4:24 | function h() {} | -| arguments | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| arguments | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| arguments | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| arguments | for.js:1:2:5:1 | functio ... x;\\n} | -| arguments | let.js:14:1:21:1 | functio ... }\\n} | -| arguments | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| arguments | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | -| arguments | variables.js:8:1:12:1 | functio ... ar x;\\n} | -| arguments | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| arguments | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | -| f | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| g | assignments.js:3:1:6:1 | functio ... = 56;\\n} | -| g | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| g | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| h | assignments.js:4:10:4:24 | function h() {} | -| h | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| o | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| o | for.js:1:2:5:1 | functio ... x;\\n} | -| x | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | -| x | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | -| x | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| x | for.js:1:2:5:1 | functio ... x;\\n} | -| x | legacyletstmt.js:1:1:8:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:1:1:22:0 | | -| x | let.js:14:1:21:1 | functio ... }\\n} | -| x | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | -| x | variables.js:8:1:12:1 | functio ... ar x;\\n} | -| x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| y | defaultargs.js:3:3:3:25 | functio ... = x) {} | -| y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| y | legacyletstmt.js:1:1:8:0 | | -| y | let.js:1:1:22:0 | | -| y | let.js:14:1:21:1 | functio ... }\\n} | -| y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | -| y | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| y | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | -| z | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | -| z | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| arrayPatternDefault.js:1:2:1:1 | arguments | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| arrayPatternDefault.js:1:11:1:11 | o | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| arrayPatternDefault.js:2:8:2:8 | x | arrayPatternDefault.js:1:2:4:1 | functio ... bal2;\\n} | +| assignments.js:3:1:3:0 | arguments | assignments.js:3:1:6:1 | functio ... = 56;\\n} | +| assignments.js:4:6:4:6 | g | assignments.js:3:1:6:1 | functio ... = 56;\\n} | +| assignments.js:4:10:4:9 | arguments | assignments.js:4:10:4:24 | function h() {} | +| assignments.js:4:19:4:19 | h | assignments.js:4:10:4:24 | function h() {} | +| defaultargs.js:2:7:2:7 | x | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:2:10:2:18 | arguments | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:3:3:3:2 | arguments | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:3:12:3:12 | f | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:3:14:3:14 | x | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:3:17:3:17 | y | defaultargs.js:3:3:3:25 | functio ... = x) {} | +| defaultargs.js:4:3:4:2 | arguments | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| defaultargs.js:4:12:4:12 | g | defaultargs.js:1:2:5:1 | functio ... ]) {}\\n} | +| defaultargs.js:4:14:4:14 | x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| defaultargs.js:4:32:4:32 | y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | +| for.js:1:2:1:1 | arguments | for.js:1:2:5:1 | functio ... x;\\n} | +| for.js:1:11:1:11 | o | for.js:1:2:5:1 | functio ... x;\\n} | +| for.js:2:7:2:7 | x | for.js:1:2:5:1 | functio ... x;\\n} | +| legacyletstmt.js:3:6:3:6 | x | legacyletstmt.js:1:1:8:0 | | +| legacyletstmt.js:3:14:3:14 | y | legacyletstmt.js:1:1:8:0 | | +| let.js:2:9:2:9 | x | let.js:1:1:22:0 | | +| let.js:4:13:4:13 | x | let.js:1:1:22:0 | | +| let.js:5:18:5:18 | x | let.js:1:1:22:0 | | +| let.js:5:26:5:26 | y | let.js:1:1:22:0 | | +| let.js:6:17:6:17 | x | let.js:1:1:22:0 | | +| let.js:9:18:9:18 | x | let.js:1:1:22:0 | | +| let.js:14:1:14:0 | arguments | let.js:14:1:21:1 | functio ... }\\n} | +| let.js:14:14:14:14 | x | let.js:14:1:21:1 | functio ... }\\n} | +| let.js:17:11:17:11 | y | let.js:14:1:21:1 | functio ... }\\n} | +| typeoftype.ts:1:1:1:0 | arguments | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:2:7:2:7 | x | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:3:3:3:2 | arguments | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | +| typeoftype.ts:3:12:3:12 | g | typeoftype.ts:1:1:6:1 | functio ... x\\n }\\n} | +| typeoftype.ts:4:9:4:9 | y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | +| variables.js:8:1:8:0 | arguments | variables.js:8:1:12:1 | functio ... ar x;\\n} | +| variables.js:9:6:9:6 | x | variables.js:8:1:12:1 | functio ... ar x;\\n} | +| variables.js:13:1:13:0 | arguments | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:13:12:13:12 | y | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:13:15:13:15 | z | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:15:6:15:6 | x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:16:2:16:1 | arguments | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| variables.js:16:11:16:11 | h | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | +| variables.js:16:13:16:13 | z | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | +| variables.js:18:11:18:11 | y | variables.js:16:2:22:2 | functio ... y+z;\\n\\t} | diff --git a/javascript/ql/test/qlpack.yml b/javascript/ql/test/qlpack.yml index d40472ed653..76f050e0b81 100644 --- a/javascript/ql/test/qlpack.yml +++ b/javascript/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-javascript-tests version: 0.0.0 libraryPathDependencies: codeql-javascript +extractor: javascript diff --git a/javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst.ts b/javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst.ts rename to javascript/ql/test/query-tests/Declarations/ConflictingFunctions/tst2.ts diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected index 52143fd3d7b..88b5fc55b25 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/DeadStoreOfLocal.expected @@ -1,12 +1,13 @@ -| overload.ts:10:12:10:14 | baz | This definition of baz is useless, since its value is never read. | +| overload.ts:10:12:10:14 | baz | The value assigned to baz here is unused. | | tst2.js:26:9:26:14 | x = 23 | The initial value of x is unused, since it is always overwritten. | -| tst2.js:28:9:28:14 | x = 42 | This definition of x is useless, since its value is never read. | -| tst3.js:2:1:2:36 | exports ... a: 23 } | This definition of exports is useless, since its value is never read. | -| tst3b.js:2:18:2:36 | exports = { a: 23 } | This definition of exports is useless, since its value is never read. | -| tst.js:6:2:6:7 | y = 23 | This definition of y is useless, since its value is never read. | +| tst2.js:28:9:28:14 | x = 42 | The value assigned to x here is unused. | +| tst3.js:2:1:2:36 | exports ... a: 23 } | The value assigned to exports here is unused. | +| tst3b.js:2:18:2:36 | exports = { a: 23 } | The value assigned to exports here is unused. | +| tst.js:6:2:6:7 | y = 23 | The value assigned to y here is unused. | | tst.js:13:6:13:11 | a = 23 | The initial value of a is unused, since it is always overwritten. | -| tst.js:13:14:13:19 | a = 42 | This definition of a is useless, since its value is never read. | +| tst.js:13:14:13:19 | a = 42 | The value assigned to a here is unused. | | tst.js:45:6:45:11 | x = 23 | The initial value of x is unused, since it is always overwritten. | | tst.js:51:6:51:11 | x = 23 | The initial value of x is unused, since it is always overwritten. | | tst.js:132:7:132:13 | {x} = o | The initial value of x is unused, since it is always overwritten. | | tst.js:162:6:162:14 | [x] = [0] | The initial value of x is unused, since it is always overwritten. | +| tst.js:172:7:172:17 | nSign = foo | The value assigned to nSign here is unused. | diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js index c398cf3370e..f19b1656da2 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/tst.js @@ -166,3 +166,11 @@ function v() { x; y; }); + +(function() { + if (something()) { + var nSign = foo; + } else { + console.log(nSign); + } +})() diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected b/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected index f976725b559..7bc922c7171 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected +++ b/javascript/ql/test/query-tests/Declarations/UnusedProperty/UnusedProperty.expected @@ -1,3 +1,4 @@ +| tst2.ts:24:21:24:25 | p: 42 | Unused property p. | | tst.js:4:9:4:19 | unused1: 42 | Unused property unused1. | | tst.js:19:5:19:15 | unused9: 42 | Unused property unused9. | | tst.js:26:13:26:24 | unused11: 42 | Unused property unused11. | @@ -6,4 +7,3 @@ | tst.js:52:3:52:14 | unused14: 42 | Unused property unused14. | | tst.js:54:2:54:20 | captured14.unused14 | Unused property unused14. | | tst.js:55:2:55:20 | captured14.unused14 | Unused property unused14. | -| tst.ts:24:21:24:25 | p: 42 | Unused property p. | diff --git a/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.ts b/javascript/ql/test/query-tests/Declarations/UnusedProperty/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Declarations/UnusedProperty/tst.ts rename to javascript/ql/test/query-tests/Declarations/UnusedProperty/tst2.ts diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts new file mode 100644 index 00000000000..4362c11a8e6 --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsTest.ts @@ -0,0 +1,5 @@ +declare let cache: { [x: string]: Promise }; + +function deleteCache(x: string) { + delete cache[x]; // OK +} diff --git a/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json new file mode 100644 index 00000000000..82194fc7ab0 --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/MissingAwait/tsconfig.json @@ -0,0 +1,3 @@ +{ + "include": ["."] +} diff --git a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected index 43098d60483..535682017e4 100644 --- a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected +++ b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/MisspelledVariableName.expected @@ -1,5 +1,13 @@ | MisspelledVariableName.js:2:40:2:45 | lenght | 'lenght' may be a typo for variable $@. | MisspelledVariableName.js:2:19:2:24 | length | length | | tst.js:2:10:2:20 | errorMesage | 'errorMesage' may be a typo for variable $@. | tst.js:1:12:1:23 | errorMessage | errorMessage | -| tst.js:6:10:6:21 | errorMessage | 'errorMessage' may be a typo for variable $@. | tst.js:5:12:5:22 | errorMesage | errorMesage | +| tst.js:6:10:6:21 | errorMessage | $@ may be a typo for 'errorMessage'. | tst.js:5:12:5:22 | errorMesage | errorMesage | | tst.js:11:12:11:22 | errorMesage | 'errorMesage' may be a typo for variable $@. | tst.js:9:12:9:23 | errorMessage | errorMessage | -| tst.js:17:5:17:16 | errorMessage | 'errorMessage' may be a typo for variable $@. | tst.js:15:12:15:22 | errorMesage | errorMesage | +| tst.js:17:5:17:16 | errorMessage | $@ may be a typo for 'errorMessage'. | tst.js:15:12:15:22 | errorMesage | errorMesage | +| tst.js:22:2:22:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:23:2:23:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:24:2:24:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:25:2:25:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:26:2:26:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:27:2:27:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:28:2:28:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | +| tst.js:29:2:29:12 | thisHandler | $@ may be a typo for 'thisHandler'. | tst.js:21:6:21:15 | thisHander | thisHander | diff --git a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js index bc669b52957..cd6c027f1fc 100644 --- a/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js +++ b/javascript/ql/test/query-tests/Expressions/MisspelledVariableName/tst.js @@ -16,3 +16,15 @@ function k(errorMesage) { let inner = () => errorMessage; } + +function foo() { + var thisHander; + thisHandler.foo1; + thisHandler.foo2; + thisHandler.foo3; + thisHandler.foo4; + thisHandler.foo5; + thisHandler.foo6; + thisHandler.foo7; + thisHandler.foo8; +} \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected index 672ea838983..8198d8d7c1c 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/SuspiciousPropAccess.expected @@ -1,6 +1,6 @@ | SuspiciousPropAccess.js:4:10:4:21 | result.value | The base expression of this property access is always undefined. | | optional-chaining.js:3:5:3:7 | a.p | The base expression of this property access is always null. | | optional-chaining.js:7:5:7:7 | b.p | The base expression of this property access is always undefined. | +| tst2.ts:19:3:19:5 | x.p | The base expression of this property access is always undefined. | | tst.js:32:32:32:38 | a(1)[0] | The base expression of this property access is always null. | -| tst.ts:19:3:19:5 | x.p | The base expression of this property access is always undefined. | | typeassertion.ts:14:3:14:9 | z.field | The base expression of this property access is always null. | diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst.ts b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst.ts rename to javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/tst2.ts diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected index de7800f58fd..05b255fad02 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.expected @@ -1 +1,5 @@ -| IncompleteUrlSchemeCheck.js:3:9:3:35 | u.start ... ript:") | This check does not consider data: and vbscript:. | +| IncompleteUrlSchemeCheck.js:5:9:5:35 | u.start ... ript:") | This check does not consider data: and vbscript:. | +| IncompleteUrlSchemeCheck.js:16:9:16:39 | badProt ... otocol) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:23:9:23:43 | badProt ... scheme) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:30:9:30:43 | badProt ... scheme) | This check does not consider vbscript:. | +| IncompleteUrlSchemeCheck.js:37:9:37:31 | scheme ... script" | This check does not consider data: and vbscript:. | diff --git a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js index 270cff2d821..617bb224da9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js +++ b/javascript/ql/test/query-tests/Security/CWE-020/IncompleteUrlSchemeCheck.js @@ -1,6 +1,47 @@ +import * as dummy from 'dummy'; + function sanitizeUrl(url) { let u = decodeURI(url).trim().toLowerCase(); - if (u.startsWith("javascript:")) + if (u.startsWith("javascript:")) // NOT OK + return "about:blank"; + return url; +} + +let badProtocols = ['javascript:', 'data:']; +let badProtocolNoColon = ['javascript', 'data']; +let badProtocolsGood = ['javascript:', 'data:', 'vbscript:']; + +function test2(url) { + let protocol = new URL(url).protocol; + if (badProtocols.includes(protocol)) // NOT OK + return "about:blank"; + return url; +} + +function test3(url) { + let scheme = goog.uri.utils.getScheme(url); + if (badProtocolNoColon.includes(scheme)) // NOT OK + return "about:blank"; + return url; +} + +function test4(url) { + let scheme = url.split(':')[0]; + if (badProtocolNoColon.includes(scheme)) // NOT OK + return "about:blank"; + return url; +} + +function test5(url) { + let scheme = url.split(':')[0]; + if (scheme === "javascript") // NOT OK + return "about:blank"; + return url; +} + +function test6(url) { + let protocol = new URL(url).protocol; + if (badProtocolsGood.includes(protocol)) // OK return "about:blank"; return url; } diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected index ec4531fde13..914c2099868 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected @@ -1277,6 +1277,48 @@ nodes | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:202:50:202:53 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | | normalizedPaths.js:11:7:11:27 | path | @@ -2040,6 +2082,92 @@ nodes | other-fs-libraries.js:24:35:24:38 | path | | other-fs-libraries.js:24:35:24:38 | path | | other-fs-libraries.js:24:35:24:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:38:24:38:30 | req.url | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:40:35:40:38 | path | | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-require.js:7:19:7:37 | req.param("module") | @@ -4385,6 +4513,22 @@ edges | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | | TaintedPath.js:173:7:173:48 | path | TaintedPath.js:186:29:186:32 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:201:40:201:43 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | +| TaintedPath.js:173:7:173:48 | path | TaintedPath.js:202:50:202:53 | path | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | | TaintedPath.js:173:14:173:37 | url.par ... , true) | TaintedPath.js:173:14:173:43 | url.par ... ).query | @@ -4561,6 +4705,62 @@ edges | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | | TaintedPath.js:186:29:186:32 | path | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:43 | path | TaintedPath.js:201:40:201:73 | path.re ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:201:40:201:73 | path.re ... +/, '') | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:29:202:54 | pathMod ... e(path) | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | +| TaintedPath.js:202:50:202:53 | path | TaintedPath.js:202:29:202:54 | pathMod ... e(path) | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | | normalizedPaths.js:11:7:11:27 | path | normalizedPaths.js:13:19:13:22 | path | @@ -5559,6 +5759,118 @@ edges | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:9:14:9:37 | url.par ... , true) | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:7:38:48 | path | other-fs-libraries.js:40:35:40:38 | path | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:37 | url.par ... , true) | other-fs-libraries.js:38:14:38:43 | url.par ... ).query | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:43 | url.par ... ).query | other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:14:38:48 | url.par ... ry.path | other-fs-libraries.js:38:7:38:48 | path | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | +| other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:38:14:38:37 | url.par ... , true) | | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | @@ -6391,6 +6703,8 @@ edges | TaintedPath.js:184:29:184:53 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:184:29:184:53 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | TaintedPath.js:185:29:185:51 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:185:29:185:51 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:186:29:186:57 | path.re ... /g, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | +| TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:201:29:201:73 | "prefix ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | +| TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | TaintedPath.js:173:24:173:30 | req.url | TaintedPath.js:202:29:202:84 | pathMod ... +/, '') | This path depends on $@. | TaintedPath.js:173:24:173:30 | req.url | a user-provided value | | normalizedPaths.js:13:19:13:22 | path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:13:19:13:22 | path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | | normalizedPaths.js:14:19:14:29 | './' + path | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:14:19:14:29 | './' + path | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | | normalizedPaths.js:15:19:15:38 | path + '/index.html' | normalizedPaths.js:11:14:11:27 | req.query.path | normalizedPaths.js:15:19:15:38 | path + '/index.html' | This path depends on $@. | normalizedPaths.js:11:14:11:27 | req.query.path | a user-provided value | @@ -6456,6 +6770,7 @@ edges | other-fs-libraries.js:17:35:17:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:17:35:17:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | | other-fs-libraries.js:19:56:19:59 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:19:56:19:59 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | | other-fs-libraries.js:24:35:24:38 | path | other-fs-libraries.js:9:24:9:30 | req.url | other-fs-libraries.js:24:35:24:38 | path | This path depends on $@. | other-fs-libraries.js:9:24:9:30 | req.url | a user-provided value | +| other-fs-libraries.js:40:35:40:38 | path | other-fs-libraries.js:38:24:38:30 | req.url | other-fs-libraries.js:40:35:40:38 | path | This path depends on $@. | other-fs-libraries.js:38:24:38:30 | req.url | a user-provided value | | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value | | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:8:16:8:33 | req.param("gimme") | a user-provided value | | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:10:16:10:33 | req.param("gimme") | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js index 0ecf680367f..506dc280a3d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.js @@ -191,4 +191,13 @@ var server = http.createServer(function(req, res) { res.write(fs.readFileSync(path.replace(/\./g, ''))); // OK res.write(fs.readFileSync(path.replace(/\.\.|BLA/g, ''))); // OK } + + // removing of "../" from prefix. + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.[\/\\])+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)+/, ''))); // OK + res.write(fs.readFileSync("prefix" + pathModule.normalize(path).replace(/(\.\.\/)*/, ''))); // OK + + res.write(fs.readFileSync("prefix" + path.replace(/^(\.\.[\/\\])+/, ''))); // NOT OK - not normalized + res.write(fs.readFileSync(pathModule.normalize(path).replace(/^(\.\.[\/\\])+/, ''))); // NOT OK (can be absolute) }); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js index 611aac86f30..5eb1d0d6524 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/other-fs-libraries.js @@ -31,3 +31,11 @@ function getFsModule(special) { return require("original-fs"); } } + +var util = require("util"); + +http.createServer(function(req, res) { + var path = url.parse(req.url, true).query.path; + + util.promisify(fs.readFileSync)(path); // NOT OK +}); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index 589deda96c9..caffc921a77 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/javascript/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -39,6 +39,14 @@ nodes | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:46:54:48 | cmd | +| child_process-test.js:70:9:70:49 | cmd | +| child_process-test.js:70:15:70:38 | url.par ... , true) | +| child_process-test.js:70:15:70:44 | url.par ... ).query | +| child_process-test.js:70:15:70:49 | url.par ... ry.path | +| child_process-test.js:70:25:70:31 | req.url | +| child_process-test.js:70:25:70:31 | req.url | +| child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:72:29:72:31 | cmd | | execSeries.js:3:20:3:22 | arr | | execSeries.js:6:14:6:16 | arr | | execSeries.js:6:14:6:21 | arr[i++] | @@ -129,6 +137,13 @@ edges | child_process-test.js:53:54:53:56 | cmd | child_process-test.js:53:46:53:57 | ["bar", cmd] | | child_process-test.js:54:46:54:48 | cmd | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | | child_process-test.js:54:46:54:48 | cmd | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | +| child_process-test.js:70:9:70:49 | cmd | child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:70:9:70:49 | cmd | child_process-test.js:72:29:72:31 | cmd | +| child_process-test.js:70:15:70:38 | url.par ... , true) | child_process-test.js:70:15:70:44 | url.par ... ).query | +| child_process-test.js:70:15:70:44 | url.par ... ).query | child_process-test.js:70:15:70:49 | url.par ... ry.path | +| child_process-test.js:70:15:70:49 | url.par ... ry.path | child_process-test.js:70:9:70:49 | cmd | +| child_process-test.js:70:25:70:31 | req.url | child_process-test.js:70:15:70:38 | url.par ... , true) | +| child_process-test.js:70:25:70:31 | req.url | child_process-test.js:70:15:70:38 | url.par ... , true) | | execSeries.js:3:20:3:22 | arr | execSeries.js:6:14:6:16 | arr | | execSeries.js:6:14:6:16 | arr | execSeries.js:6:14:6:21 | arr[i++] | | execSeries.js:6:14:6:21 | arr[i++] | execSeries.js:14:24:14:30 | command | @@ -197,6 +212,7 @@ edges | child_process-test.js:54:5:54:50 | cp.spaw ... t(cmd)) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:54:25:54:49 | ['/C', ... at(cmd) | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | | child_process-test.js:59:5:59:39 | cp.exec ... , args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:50:15:50:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | | child_process-test.js:64:3:64:21 | cp.spawn(cmd, args) | child_process-test.js:6:25:6:31 | req.url | child_process-test.js:43:15:43:17 | cmd | This command depends on $@. | child_process-test.js:6:25:6:31 | req.url | a user-provided value | +| child_process-test.js:72:29:72:31 | cmd | child_process-test.js:70:25:70:31 | req.url | child_process-test.js:72:29:72:31 | cmd | This command depends on $@. | child_process-test.js:70:25:70:31 | req.url | a user-provided value | | execSeries.js:14:41:14:47 | command | execSeries.js:18:34:18:40 | req.url | execSeries.js:14:41:14:47 | command | This command depends on $@. | execSeries.js:18:34:18:40 | req.url | a user-provided value | | other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | | other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | This command depends on $@. | other.js:5:25:5:31 | req.url | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js b/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js index c9ece717eb0..c85b4907a3b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js +++ b/javascript/ql/test/query-tests/Security/CWE-078/child_process-test.js @@ -63,3 +63,12 @@ var server = http.createServer(function(req, res) { function run(cmd, args) { cp.spawn(cmd, args); // NOT OK } + +var util = require("util") + +http.createServer(function(req, res) { + let cmd = url.parse(req.url, true).query.path; + + util.promisify(cp.exec)(cmd); // NOT OK +}); + diff --git a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected index 5f1063745ae..f14ca1e8e50 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected @@ -333,6 +333,14 @@ nodes | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | +| tst.js:330:18:330:34 | document.location | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | +| tst.js:347:20:347:36 | document.location | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:20:13:20:45 | target | | typeahead.js:20:22:20:38 | document.location | | typeahead.js:20:22:20:38 | document.location | @@ -643,6 +651,14 @@ edges | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:20:13:20:45 | target | typeahead.js:21:12:21:17 | target | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | | typeahead.js:20:22:20:38 | document.location | typeahead.js:20:22:20:45 | documen ... .search | @@ -742,6 +758,8 @@ edges | tst.js:306:20:306:20 | e | tst.js:304:9:304:16 | location | tst.js:306:20:306:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:304:9:304:16 | location | user-provided value | | tst.js:314:20:314:20 | e | tst.js:311:10:311:17 | location | tst.js:314:20:314:20 | e | Cross-site scripting vulnerability due to $@. | tst.js:311:10:311:17 | location | user-provided value | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | Cross-site scripting vulnerability due to $@. | tst.js:319:35:319:42 | location | user-provided value | +| tst.js:336:18:336:35 | params.get('name') | tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | Cross-site scripting vulnerability due to $@. | tst.js:330:18:330:34 | document.location | user-provided value | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | Cross-site scripting vulnerability due to $@. | tst.js:347:20:347:36 | document.location | user-provided value | | typeahead.js:25:18:25:20 | val | typeahead.js:20:22:20:38 | document.location | typeahead.js:25:18:25:20 | val | Cross-site scripting vulnerability due to $@. | typeahead.js:20:22:20:38 | document.location | user-provided value | | v-html.vue:2:8:2:23 | v-html=tainted | v-html.vue:6:42:6:58 | document.location | v-html.vue:2:8:2:23 | v-html=tainted | Cross-site scripting vulnerability due to $@. | v-html.vue:6:42:6:58 | document.location | user-provided value | | winjs.js:3:43:3:49 | tainted | winjs.js:2:17:2:33 | document.location | winjs.js:3:43:3:49 | tainted | Cross-site scripting vulnerability due to $@. | winjs.js:2:17:2:33 | document.location | user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected index 825c4d35fe5..26baec56ee4 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected +++ b/javascript/ql/test/query-tests/Security/CWE-079/XssWithAdditionalSources.expected @@ -333,6 +333,14 @@ nodes | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | +| tst.js:330:18:330:34 | document.location | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | +| tst.js:347:20:347:36 | document.location | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:9:28:9:30 | loc | | typeahead.js:9:28:9:30 | loc | | typeahead.js:10:16:10:18 | loc | @@ -647,6 +655,14 @@ edges | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:313:10:313:10 | e | tst.js:314:20:314:20 | e | | tst.js:319:35:319:42 | location | tst.js:319:35:319:42 | location | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:330:18:330:34 | document.location | tst.js:336:18:336:35 | params.get('name') | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | +| tst.js:347:20:347:36 | document.location | tst.js:349:5:349:30 | getUrl( ... ring(1) | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | | typeahead.js:9:28:9:30 | loc | typeahead.js:10:16:10:18 | loc | diff --git a/javascript/ql/test/query-tests/Security/CWE-079/tst.js b/javascript/ql/test/query-tests/Security/CWE-079/tst.js index 1ec5610ff83..99a50e9ab9c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-079/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-079/tst.js @@ -324,4 +324,28 @@ function test2() { // OK $('myId').html(target.length) +} + +function getTaintedUrl() { + return new URL(document.location); +} + +function URLPseudoProperties() { + // NOT OK + let params = getTaintedUrl().searchParams; + $('name').html(params.get('name')); + + // OK (.get is not defined on a URL) + let myUrl = getTaintedUrl(); + $('name').html(myUrl.get('name')); + +} + + +function hash() { + function getUrl() { + return new URL(document.location); + } + $(getUrl().hash.substring(1)); // NOT OK + } \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index dd7f524e3bf..1cbbd9faa5a 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,3 +1,4 @@ +| tst2.ts:6:13:6:25 | returnsVoid() | the $@ does not return anything, yet the return value is used. | tst2.ts:1:1:1:38 | declare ... : void; | function returnsVoid | | tst.html:19:31:19:43 | addHandlers() | the $@ does not return anything, yet the return value is used. | tst.html:5:7:12:7 | functio ... } | function addHandlers | | tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | @@ -6,4 +7,3 @@ | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | | tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | | tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | -| tst.ts:6:13:6:25 | returnsVoid() | the $@ does not return anything, yet the return value is used. | tst.ts:1:1:1:38 | declare ... : void; | function returnsVoid | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.ts b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst2.ts similarity index 100% rename from javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.ts rename to javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst2.ts diff --git a/misc/suite-helpers/code-scanning-selectors.yml b/misc/suite-helpers/code-scanning-selectors.yml new file mode 100644 index 00000000000..ffa40d8e4b1 --- /dev/null +++ b/misc/suite-helpers/code-scanning-selectors.yml @@ -0,0 +1,16 @@ +- description: Selectors for selecting the Code-Scanning-relevant queries for a language +- include: + kind: + - problem + - path-problem + precision: + - high + - very-high + problem.severity: + - error + - warning + tags contain: + - security +- exclude: + deprecated: // + diff --git a/python/ql/examples/snippets/builtin_object.ql b/python/ql/examples/snippets/builtin_object.ql index fd404aea563..7f552a5aa79 100644 --- a/python/ql/examples/snippets/builtin_object.ql +++ b/python/ql/examples/snippets/builtin_object.ql @@ -6,7 +6,7 @@ * builtin * object */ - + import python from Expr e, string name diff --git a/python/ql/examples/snippets/call.ql b/python/ql/examples/snippets/call.ql index d829802fd82..b326024a33c 100644 --- a/python/ql/examples/snippets/call.ql +++ b/python/ql/examples/snippets/call.ql @@ -5,7 +5,7 @@ * @tags call * function */ - + import python from Value len, CallNode call diff --git a/python/ql/examples/snippets/catch_exception.ql b/python/ql/examples/snippets/catch_exception.ql index e6f66a321c4..c117267d112 100644 --- a/python/ql/examples/snippets/catch_exception.ql +++ b/python/ql/examples/snippets/catch_exception.ql @@ -6,11 +6,11 @@ * try * exception */ - + import python from ExceptStmt ex, ClassValue cls -where +where cls.getName() = "MyExceptionClass" and ex.getType().pointsTo(cls) select ex diff --git a/python/ql/examples/snippets/conditional_expression.ql b/python/ql/examples/snippets/conditional_expression.ql index 3081d14757d..ee519aedb06 100644 --- a/python/ql/examples/snippets/conditional_expression.ql +++ b/python/ql/examples/snippets/conditional_expression.ql @@ -11,7 +11,8 @@ import python from IfExp e, ClassObject cls1, ClassObject cls2 -where - e.getBody().refersTo(_, cls1, _) and e.getOrelse().refersTo(_, cls2, _) and +where + e.getBody().refersTo(_, cls1, _) and + e.getOrelse().refersTo(_, cls2, _) and cls1 != cls2 -select e \ No newline at end of file +select e diff --git a/python/ql/examples/snippets/emptyblock.ql b/python/ql/examples/snippets/emptyblock.ql index 8f05150dc41..b45bb2f02c9 100644 --- a/python/ql/examples/snippets/emptyblock.ql +++ b/python/ql/examples/snippets/emptyblock.ql @@ -6,7 +6,7 @@ * block * statement */ - + import python from StmtList blk diff --git a/python/ql/examples/snippets/emptythen.ql b/python/ql/examples/snippets/emptythen.ql index 4c23c05ee71..bc017d4707a 100644 --- a/python/ql/examples/snippets/emptythen.ql +++ b/python/ql/examples/snippets/emptythen.ql @@ -1,7 +1,7 @@ /** * @id py/examples/emptythen * @name If statements with empty then branch - * @description Finds 'if' statements where the "then" branch + * @description Finds 'if' statements where the "then" branch * consists entirely of Pass statements * @tags if * then @@ -9,13 +9,13 @@ * conditional * branch */ - + import python from If i where not exists(Stmt s | - i.getStmt(_) = s and + i.getStmt(_) = s and not s instanceof Pass ) select i diff --git a/python/ql/examples/snippets/eq_true.ql b/python/ql/examples/snippets/eq_true.ql index 01c49d4d900..46091ea5474 100644 --- a/python/ql/examples/snippets/eq_true.ql +++ b/python/ql/examples/snippets/eq_true.ql @@ -6,7 +6,7 @@ * test * boolean */ - + import python from Compare eq diff --git a/python/ql/examples/snippets/equalitystmt.ql b/python/ql/examples/snippets/equalitystmt.ql index 674037ab2e6..60dd8880515 100644 --- a/python/ql/examples/snippets/equalitystmt.ql +++ b/python/ql/examples/snippets/equalitystmt.ql @@ -6,7 +6,7 @@ * equality * expression statement */ - + import python from ExprStmt e, Compare eq diff --git a/python/ql/examples/snippets/extend_class.ql b/python/ql/examples/snippets/extend_class.ql index 038fc78a9f2..cc4dd62647d 100644 --- a/python/ql/examples/snippets/extend_class.ql +++ b/python/ql/examples/snippets/extend_class.ql @@ -9,11 +9,11 @@ * subtype * supertype */ - + import python from ClassObject sub, ClassObject base -where +where base.getName() = "MyClass" and sub.getABaseType() = base select sub diff --git a/python/ql/examples/snippets/filename.ql b/python/ql/examples/snippets/filename.ql index eb8b9ccb7a2..579cceea47a 100644 --- a/python/ql/examples/snippets/filename.ql +++ b/python/ql/examples/snippets/filename.ql @@ -4,7 +4,7 @@ * @description Finds files called `spam.py` * @tags file */ - + import python from File f diff --git a/python/ql/examples/snippets/generator.ql b/python/ql/examples/snippets/generator.ql index c374895c8e6..573d8a2f757 100644 --- a/python/ql/examples/snippets/generator.ql +++ b/python/ql/examples/snippets/generator.ql @@ -10,4 +10,4 @@ import python from Function f where f.isGenerator() -select f \ No newline at end of file +select f diff --git a/python/ql/examples/snippets/integer_literal.ql b/python/ql/examples/snippets/integer_literal.ql index 1a1b4685ce8..debf88ca384 100644 --- a/python/ql/examples/snippets/integer_literal.ql +++ b/python/ql/examples/snippets/integer_literal.ql @@ -5,7 +5,7 @@ * @tags integer * literal */ - + import python from IntegerLiteral literal diff --git a/python/ql/examples/snippets/method_call.ql b/python/ql/examples/snippets/method_call.ql index c0b119c364c..9f78a4bb22f 100644 --- a/python/ql/examples/snippets/method_call.ql +++ b/python/ql/examples/snippets/method_call.ql @@ -5,11 +5,11 @@ * @tags call * method */ - + import python from AstNode call, PythonFunctionValue method -where +where method.getQualifiedName() = "MyClass.methodName" and method.getACall().getNode() = call select call diff --git a/python/ql/examples/snippets/new_instance.ql b/python/ql/examples/snippets/new_instance.ql index f6ede9fa8f6..c1293d6638c 100644 --- a/python/ql/examples/snippets/new_instance.ql +++ b/python/ql/examples/snippets/new_instance.ql @@ -6,7 +6,7 @@ * constructor * new */ - + import python from Call new, ClassValue cls diff --git a/python/ql/examples/snippets/override_method.ql b/python/ql/examples/snippets/override_method.ql index 81a02004e37..75c276df627 100644 --- a/python/ql/examples/snippets/override_method.ql +++ b/python/ql/examples/snippets/override_method.ql @@ -5,7 +5,7 @@ * @tags method * override */ - + import python from FunctionObject override, FunctionObject base diff --git a/python/ql/examples/snippets/print.ql b/python/ql/examples/snippets/print.ql index b48909fa108..1a560d48e3d 100644 --- a/python/ql/examples/snippets/print.ql +++ b/python/ql/examples/snippets/print.ql @@ -4,11 +4,11 @@ * @description Find print statements or calls to the builtin function 'print' * @tags print */ - + import python from AstNode print -where +where /* Python 2 without `from __future__ import print_function` */ print instanceof Print or diff --git a/python/ql/examples/snippets/private_access.ql b/python/ql/examples/snippets/private_access.ql index 5ea42e965d0..14548864579 100644 --- a/python/ql/examples/snippets/private_access.ql +++ b/python/ql/examples/snippets/private_access.ql @@ -1,19 +1,20 @@ /** * @id py/examples/private-access * @name Private access - * @description Find accesses to "private" attributes (those starting with an underscore) + * @description Find accesses to "private" attributes (those starting with an underscore) * @tags access * private */ - + import python predicate is_private(Attribute a) { - a.getName().matches("\\_%") and + a.getName().matches("\\_%") and not a.getName().matches("\\_\\_%\\_\\_") } from Attribute access -where is_private(access) and -not access.getObject().(Name).getId() = "self" +where + is_private(access) and + not access.getObject().(Name).getId() = "self" select access diff --git a/python/ql/examples/snippets/raise_exception.ql b/python/ql/examples/snippets/raise_exception.ql index 650af97ad6f..ce69c353780 100644 --- a/python/ql/examples/snippets/raise_exception.ql +++ b/python/ql/examples/snippets/raise_exception.ql @@ -6,13 +6,11 @@ * raise * exception */ - + import python from Raise raise, ClassValue ex where ex.getName() = "AnException" and - ( - raise.getException().pointsTo(ex.getASuperType()) - ) + raise.getException().pointsTo(ex.getASuperType()) select raise, "Don't raise instances of 'AnException'" diff --git a/python/ql/examples/snippets/raw_string.ql b/python/ql/examples/snippets/raw_string.ql index 3711d8d5171..78b1bbefb9a 100644 --- a/python/ql/examples/snippets/raw_string.ql +++ b/python/ql/examples/snippets/raw_string.ql @@ -1,11 +1,11 @@ /** * @id py/examples/raw-string * @name Raw string literals - * @description Finds string literals with an 'r' prefix + * @description Finds string literals with an 'r' prefix * @tags string * raw */ - + import python from StrConst s diff --git a/python/ql/examples/snippets/store_none.ql b/python/ql/examples/snippets/store_none.ql index dfcac497908..88aaac47f56 100644 --- a/python/ql/examples/snippets/store_none.ql +++ b/python/ql/examples/snippets/store_none.ql @@ -8,11 +8,11 @@ * collection * add */ - + import python from SubscriptNode store -where +where store.isStore() and store.getIndex().pointsTo(Value::named("None")) select store diff --git a/python/ql/examples/snippets/tryfinally.ql b/python/ql/examples/snippets/tryfinally.ql index f37b86f3fa6..bf5ea3c61a6 100644 --- a/python/ql/examples/snippets/tryfinally.ql +++ b/python/ql/examples/snippets/tryfinally.ql @@ -10,6 +10,7 @@ import python from Try t -where exists(t.getFinalbody()) - and not exists(t.getAHandler()) +where + exists(t.getFinalbody()) and + not exists(t.getAHandler()) select t diff --git a/python/ql/src/Classes/ClassAttributes.qll b/python/ql/src/Classes/ClassAttributes.qll index 262ff1058e8..5da7d29ace3 100644 --- a/python/ql/src/Classes/ClassAttributes.qll +++ b/python/ql/src/Classes/ClassAttributes.qll @@ -3,7 +3,6 @@ private import semmle.python.pointsto.PointsTo /** Helper class for UndefinedClassAttribute.ql and MaybeUndefinedClassAttribute.ql */ class CheckClass extends ClassObject { - private predicate ofInterest() { not this.unknowableAttributes() and not this.getPyClass().isProbableMixin() and @@ -19,7 +18,8 @@ class CheckClass extends ClassObject { forall(ClassObject sup | sup = this.getAnImproperSuperType() and sup.declaresAttribute("__init__") and - not sup = theObjectType() | + not sup = theObjectType() + | sup.declaredAttribute("__init__") instanceof PyFunctionObject ) } @@ -32,108 +32,111 @@ class CheckClass extends ClassObject { } predicate sometimesDefines(string name) { - this.alwaysDefines(name) or - exists(SelfAttributeStore sa | - sa.getScope().getScope+() = this.getAnImproperSuperType().getPyClass() | + this.alwaysDefines(name) + or + exists(SelfAttributeStore sa | + sa.getScope().getScope+() = this.getAnImproperSuperType().getPyClass() + | name = sa.getName() ) } private predicate selfDictAssigns() { - exists(Assign a, SelfAttributeRead self_dict, Subscript sub | + exists(Assign a, SelfAttributeRead self_dict, Subscript sub | self_dict.getName() = "__dict__" and - ( - self_dict = sub.getObject() - or - /* Indirect assignment via temporary variable */ - exists(SsaVariable v | - v.getAUse() = sub.getObject().getAFlowNode() and - v.getDefinition().(DefinitionNode).getValue() = self_dict.getAFlowNode() - ) + ( + self_dict = sub.getObject() + or + /* Indirect assignment via temporary variable */ + exists(SsaVariable v | + v.getAUse() = sub.getObject().getAFlowNode() and + v.getDefinition().(DefinitionNode).getValue() = self_dict.getAFlowNode() + ) ) and a.getATarget() = sub and - exists(FunctionObject meth | meth = this.lookupAttribute(_) and a.getScope() = meth.getFunction()) + exists(FunctionObject meth | + meth = this.lookupAttribute(_) and a.getScope() = meth.getFunction() + ) ) } - pragma [nomagic] + pragma[nomagic] private predicate monkeyPatched(string name) { exists(Attribute a | - a.getCtx() instanceof Store and - PointsTo::points_to(a.getObject().getAFlowNode(), _, this, _, _) and a.getName() = name + a.getCtx() instanceof Store and + PointsTo::points_to(a.getObject().getAFlowNode(), _, this, _, _) and + a.getName() = name ) } private predicate selfSetattr() { - exists(Call c, Name setattr, Name self, Function method | - ( method.getScope() = this.getPyClass() or - method.getScope() = this.getASuperType().getPyClass() - ) and - c.getScope() = method and - c.getFunc() = setattr and - setattr.getId() = "setattr" and - c.getArg(0) = self and - self.getId() = "self" - ) + exists(Call c, Name setattr, Name self, Function method | + ( + method.getScope() = this.getPyClass() or + method.getScope() = this.getASuperType().getPyClass() + ) and + c.getScope() = method and + c.getFunc() = setattr and + setattr.getId() = "setattr" and + c.getArg(0) = self and + self.getId() = "self" + ) } - predicate interestingUndefined(SelfAttributeRead a) { - exists(string name | name = a.getName() | - interestingContext(a, name) and - not this.definedInBlock(a.getAFlowNode().getBasicBlock(), name) - ) - } + predicate interestingUndefined(SelfAttributeRead a) { + exists(string name | name = a.getName() | + interestingContext(a, name) and + not this.definedInBlock(a.getAFlowNode().getBasicBlock(), name) + ) + } - private predicate interestingContext(SelfAttributeRead a, string name) { - name = a.getName() and - this.ofInterest() and - this.getPyClass() = a.getScope().getScope() and - not a.locallyDefined() and - not a.guardedByHasattr() and - a.getScope().isPublic() and - not this.monkeyPatched(name) and - not attribute_assigned_in_method(lookupAttribute("setUp"), name) - } + private predicate interestingContext(SelfAttributeRead a, string name) { + name = a.getName() and + this.ofInterest() and + this.getPyClass() = a.getScope().getScope() and + not a.locallyDefined() and + not a.guardedByHasattr() and + a.getScope().isPublic() and + not this.monkeyPatched(name) and + not attribute_assigned_in_method(lookupAttribute("setUp"), name) + } - private predicate probablyAbstract() { - this.getName().matches("Abstract%") - or - this.isAbstract() - } + private predicate probablyAbstract() { + this.getName().matches("Abstract%") + or + this.isAbstract() + } - private pragma[nomagic] predicate definitionInBlock(BasicBlock b, string name) { - exists(SelfAttributeStore sa | - sa.getAFlowNode().getBasicBlock() = b and sa.getName() = name and sa.getClass() = this.getPyClass() - ) - or - exists(FunctionObject method | this.lookupAttribute(_) = method | - attribute_assigned_in_method(method, name) and - b = method.getACall().getBasicBlock() - ) - } - - private pragma[nomagic] predicate definedInBlock(BasicBlock b, string name) { - // manual specialisation: this is only called from interestingUndefined, - // so we can push the context in from there, which must apply to a - // SelfAttributeRead in the same scope - exists(SelfAttributeRead a | - a.getScope() = b.getScope() and name = a.getName() | - interestingContext(a, name) - ) - and - this.definitionInBlock(b, name) - or - exists(BasicBlock prev | this.definedInBlock(prev, name) and prev.getASuccessor() = b) - } + pragma[nomagic] + private predicate definitionInBlock(BasicBlock b, string name) { + exists(SelfAttributeStore sa | + sa.getAFlowNode().getBasicBlock() = b and + sa.getName() = name and + sa.getClass() = this.getPyClass() + ) + or + exists(FunctionObject method | this.lookupAttribute(_) = method | + attribute_assigned_in_method(method, name) and + b = method.getACall().getBasicBlock() + ) + } + pragma[nomagic] + private predicate definedInBlock(BasicBlock b, string name) { + // manual specialisation: this is only called from interestingUndefined, + // so we can push the context in from there, which must apply to a + // SelfAttributeRead in the same scope + exists(SelfAttributeRead a | a.getScope() = b.getScope() and name = a.getName() | + interestingContext(a, name) + ) and + this.definitionInBlock(b, name) + or + exists(BasicBlock prev | this.definedInBlock(prev, name) and prev.getASuccessor() = b) + } } - private Object object_getattribute() { result.asBuiltin() = theObjectType().asBuiltin().getMember("__getattribute__") } -private predicate auto_name(string name) { - name = "__class__" or name = "__dict__" -} - +private predicate auto_name(string name) { name = "__class__" or name = "__dict__" } diff --git a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql index 44be7ac9157..b4829809135 100644 --- a/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql +++ b/python/ql/src/Classes/ConflictingAttributesInBaseClasses.ql @@ -15,13 +15,13 @@ import python predicate does_nothing(PyFunctionObject f) { not exists(Stmt s | s.getScope() = f.getFunction() | - not s instanceof Pass and not ((ExprStmt)s).getValue() = f.getFunction().getDocString() + not s instanceof Pass and not s.(ExprStmt).getValue() = f.getFunction().getDocString() ) } /* If a method performs a super() call then it is OK as the 'overridden' method will get called */ predicate calls_super(FunctionObject f) { - exists(Call sup, Call meth, Attribute attr, GlobalVariable v | + exists(Call sup, Call meth, Attribute attr, GlobalVariable v | meth.getScope() = f.getFunction() and meth.getFunc() = attr and attr.getObject() = sup and @@ -33,25 +33,29 @@ predicate calls_super(FunctionObject f) { /** Holds if the given name is white-listed for some reason */ predicate whitelisted(string name) { - /* The standard library specifically recommends this :( - * See https://docs.python.org/3/library/socketserver.html#asynchronous-mixins */ + /* + * The standard library specifically recommends this :( + * See https://docs.python.org/3/library/socketserver.html#asynchronous-mixins + */ + name = "process_request" } -from ClassObject c, ClassObject b1, ClassObject b2, string name, -int i1, int i2, Object o1, Object o2 -where c.getBaseType(i1) = b1 and -c.getBaseType(i2) = b2 and -i1 < i2 and o1 != o2 and -o1 = b1.lookupAttribute(name) and -o2 = b2.lookupAttribute(name) and -not name.matches("\\_\\_%\\_\\_") and -not calls_super(o1) and -not does_nothing(o2) and -not whitelisted(name) and -not o1.overrides(o2) and -not o2.overrides(o1) and -not c.declaresAttribute(name) - -select c, "Base classes have conflicting values for attribute '" + name + "': $@ and $@.", o1, o1.toString(), o2, o2.toString() - +from + ClassObject c, ClassObject b1, ClassObject b2, string name, int i1, int i2, Object o1, Object o2 +where + c.getBaseType(i1) = b1 and + c.getBaseType(i2) = b2 and + i1 < i2 and + o1 != o2 and + o1 = b1.lookupAttribute(name) and + o2 = b2.lookupAttribute(name) and + not name.matches("\\_\\_%\\_\\_") and + not calls_super(o1) and + not does_nothing(o2) and + not whitelisted(name) and + not o1.overrides(o2) and + not o2.overrides(o1) and + not c.declaresAttribute(name) +select c, "Base classes have conflicting values for attribute '" + name + "': $@ and $@.", o1, + o1.toString(), o2, o2.toString() diff --git a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql index 5b80f2fd7bf..8bf7d24b729 100644 --- a/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql +++ b/python/ql/src/Classes/DefineEqualsWhenAddingAttributes.ql @@ -15,7 +15,9 @@ import semmle.python.SelfAttribute import Equality predicate class_stores_to_attribute(ClassObject cls, SelfAttributeStore store, string name) { - exists(FunctionObject f | f = cls.declaredAttribute(_) and store.getScope() = f.getFunction() and store.getName() = name) and + exists(FunctionObject f | + f = cls.declaredAttribute(_) and store.getScope() = f.getFunction() and store.getName() = name + ) and /* Exclude classes used as metaclasses */ not cls.getASuperType() = theTypeType() } @@ -30,23 +32,26 @@ predicate should_override_eq(ClassObject cls, Object base_eq) { ) } -/** Does the non-overridden __eq__ method access the attribute, +/** + * Does the non-overridden __eq__ method access the attribute, * which implies that the __eq__ method does not need to be overridden. */ predicate superclassEqExpectsAttribute(ClassObject cls, PyFunctionObject base_eq, string attrname) { not cls.declaresAttribute("__eq__") and exists(ClassObject sup | sup = cls.getABaseType() and sup.declaredAttribute("__eq__") = base_eq | - exists(SelfAttributeRead store | - store.getName() = attrname | + exists(SelfAttributeRead store | store.getName() = attrname | store.getScope() = base_eq.getFunction() ) ) } from ClassObject cls, SelfAttributeStore store, Object base_eq -where class_stores_to_attribute(cls, store, _) and should_override_eq(cls, base_eq) and -/* Don't report overridden unittest.TestCase. -- TestCase overrides __eq__, but subclasses do not really need to. */ -not cls.getASuperType().getName() = "TestCase" and -not superclassEqExpectsAttribute(cls, base_eq, store.getName()) - -select cls, "The class '" + cls.getName() + "' does not override $@, but adds the new attribute $@.", base_eq, "'__eq__'", store, store.getName() +where + class_stores_to_attribute(cls, store, _) and + should_override_eq(cls, base_eq) and + /* Don't report overridden unittest.TestCase. -- TestCase overrides __eq__, but subclasses do not really need to. */ + not cls.getASuperType().getName() = "TestCase" and + not superclassEqExpectsAttribute(cls, base_eq, store.getName()) +select cls, + "The class '" + cls.getName() + "' does not override $@, but adds the new attribute $@.", base_eq, + "'__eq__'", store, store.getName() diff --git a/python/ql/src/Classes/Equality.qll b/python/ql/src/Classes/Equality.qll index 7f546c42ecd..27d17d863a4 100644 --- a/python/ql/src/Classes/Equality.qll +++ b/python/ql/src/Classes/Equality.qll @@ -1,6 +1,5 @@ import python - private Attribute dictAccess(LocalVariable var) { result.getName() = "__dict__" and result.getObject() = var.getAnAccess() @@ -12,18 +11,21 @@ private Call getattr(LocalVariable obj, LocalVariable attr) { result.getArg(1) = attr.getAnAccess() } -/** A generic equality method that compares all attributes in its dict, - * or compares attributes using `getattr`. */ +/** + * A generic equality method that compares all attributes in its dict, + * or compares attributes using `getattr`. + */ class GenericEqMethod extends Function { - GenericEqMethod() { this.getName() = "__eq__" and exists(LocalVariable self, LocalVariable other | - self.getAnAccess() = this.getArg(0) and self.getId() = "self" and + self.getAnAccess() = this.getArg(0) and + self.getId() = "self" and other.getAnAccess() = this.getArg(1) and - exists(Compare eq | + exists(Compare eq | eq.getOp(0) instanceof Eq or - eq.getOp(0) instanceof NotEq | + eq.getOp(0) instanceof NotEq + | // `self.__dict__ == other.__dict__` eq.getAChildNode() = dictAccess(self) and eq.getAChildNode() = dictAccess(other) @@ -40,11 +42,11 @@ class GenericEqMethod extends Function { /** An `__eq__` method that just does `self is other` */ class IdentityEqMethod extends Function { - IdentityEqMethod() { this.getName() = "__eq__" and exists(LocalVariable self, LocalVariable other | - self.getAnAccess() = this.getArg(0) and self.getId() = "self" and + self.getAnAccess() = this.getArg(0) and + self.getId() = "self" and other.getAnAccess() = this.getArg(1) and exists(Compare eq | eq.getOp(0) instanceof Is | eq.getAChildNode() = self.getAnAccess() and @@ -52,19 +54,20 @@ class IdentityEqMethod extends Function { ) ) } - } /** An (in)equality method that delegates to its complement */ class DelegatingEqualityMethod extends Function { - DelegatingEqualityMethod() { exists(Return ret, UnaryExpr not_, Compare comp, Cmpop op, Parameter p0, Parameter p1 | ret.getScope() = this and ret.getValue() = not_ and - not_.getOp() instanceof Not and not_.getOperand() = comp and - comp.compares(p0.getVariable().getAnAccess(), op, p1.getVariable().getAnAccess()) | - this.getName() = "__eq__" and op instanceof NotEq or + not_.getOp() instanceof Not and + not_.getOperand() = comp and + comp.compares(p0.getVariable().getAnAccess(), op, p1.getVariable().getAnAccess()) + | + this.getName() = "__eq__" and op instanceof NotEq + or this.getName() = "__ne__" and op instanceof Eq ) } diff --git a/python/ql/src/Classes/EqualsOrHash.ql b/python/ql/src/Classes/EqualsOrHash.ql index c748675850c..795e7f4c0ff 100644 --- a/python/ql/src/Classes/EqualsOrHash.ql +++ b/python/ql/src/Classes/EqualsOrHash.ql @@ -14,8 +14,11 @@ import python CallableValue defines_equality(ClassValue c, string name) { - (name = "__eq__" or major_version() = 2 and name = "__cmp__") - and + ( + name = "__eq__" + or + major_version() = 2 and name = "__cmp__" + ) and result = c.declaredAttribute(name) } @@ -26,8 +29,12 @@ CallableValue implemented_method(ClassValue c, string name) { } string unimplemented_method(ClassValue c) { - not exists(defines_equality(c, _)) and - (result = "__eq__" and major_version() = 3 or major_version() = 2 and result = "__eq__ or __cmp__") + not exists(defines_equality(c, _)) and + ( + result = "__eq__" and major_version() = 3 + or + major_version() = 2 and result = "__eq__ or __cmp__" + ) or /* Python 3 automatically makes classes unhashable if __eq__ is defined, but __hash__ is not */ not c.declaresAttribute(result) and result = "__hash__" and major_version() = 2 @@ -41,13 +48,15 @@ predicate unhashable(ClassValue cls) { } predicate violates_hash_contract(ClassValue c, string present, string missing, Value method) { - not unhashable(c) and - missing = unimplemented_method(c) and - method = implemented_method(c, present) and - not c.failedInference(_) + not unhashable(c) and + missing = unimplemented_method(c) and + method = implemented_method(c, present) and + not c.failedInference(_) } from ClassValue c, string present, string missing, CallableValue method -where violates_hash_contract(c, present, missing, method) and -exists(c.getScope()) // Suppress results that aren't from source -select method, "Class $@ implements " + present + " but does not define " + missing + ".", c, c.getName() +where + violates_hash_contract(c, present, missing, method) and + exists(c.getScope()) // Suppress results that aren't from source +select method, "Class $@ implements " + present + " but does not define " + missing + ".", c, + c.getName() diff --git a/python/ql/src/Classes/EqualsOrNotEquals.ql b/python/ql/src/Classes/EqualsOrNotEquals.ql index 606718bac6b..7457de441b0 100644 --- a/python/ql/src/Classes/EqualsOrNotEquals.ql +++ b/python/ql/src/Classes/EqualsOrNotEquals.ql @@ -13,16 +13,12 @@ import python import Equality -string equals_or_ne() { - result = "__eq__" or result = "__ne__" -} +string equals_or_ne() { result = "__eq__" or result = "__ne__" } predicate total_ordering(Class cls) { - exists(Attribute a | a = cls.getADecorator() | - a.getName() = "total_ordering") + exists(Attribute a | a = cls.getADecorator() | a.getName() = "total_ordering") or - exists(Name n | n = cls.getADecorator() | - n.getId() = "total_ordering") + exists(Name n | n = cls.getADecorator() | n.getId() = "total_ordering") } CallableValue implemented_method(ClassValue c, string name) { @@ -33,18 +29,20 @@ string unimplemented_method(ClassValue c) { not c.declaresAttribute(result) and result = equals_or_ne() } -predicate violates_equality_contract(ClassValue c, string present, string missing, CallableValue method) { - missing = unimplemented_method(c) and - method = implemented_method(c, present) and - not c.failedInference(_) and - not total_ordering(c.getScope()) and - /* Python 3 automatically implements __ne__ if __eq__ is defined, but not vice-versa */ - not (major_version() = 3 and present = "__eq__" and missing = "__ne__") and - not method.getScope() instanceof DelegatingEqualityMethod and - not c.lookup(missing).(CallableValue).getScope() instanceof DelegatingEqualityMethod +predicate violates_equality_contract( + ClassValue c, string present, string missing, CallableValue method +) { + missing = unimplemented_method(c) and + method = implemented_method(c, present) and + not c.failedInference(_) and + not total_ordering(c.getScope()) and + /* Python 3 automatically implements __ne__ if __eq__ is defined, but not vice-versa */ + not (major_version() = 3 and present = "__eq__" and missing = "__ne__") and + not method.getScope() instanceof DelegatingEqualityMethod and + not c.lookup(missing).(CallableValue).getScope() instanceof DelegatingEqualityMethod } from ClassValue c, string present, string missing, CallableValue method where violates_equality_contract(c, present, missing, method) - -select method, "Class $@ implements " + present + " but does not implement " + missing + ".", c, c.getName() +select method, "Class $@ implements " + present + " but does not implement " + missing + ".", c, + c.getName() diff --git a/python/ql/src/Classes/IncompleteOrdering.ql b/python/ql/src/Classes/IncompleteOrdering.ql index 767e7ce6c37..7755696bd45 100644 --- a/python/ql/src/Classes/IncompleteOrdering.ql +++ b/python/ql/src/Classes/IncompleteOrdering.ql @@ -13,17 +13,18 @@ import python predicate total_ordering(Class cls) { - exists(Attribute a | a = cls.getADecorator() | - a.getName() = "total_ordering") + exists(Attribute a | a = cls.getADecorator() | a.getName() = "total_ordering") or - exists(Name n | n = cls.getADecorator() | - n.getId() = "total_ordering") + exists(Name n | n = cls.getADecorator() | n.getId() = "total_ordering") } string ordering_name(int n) { - result = "__lt__" and n = 1 or - result = "__le__" and n = 2 or - result = "__gt__" and n = 3 or + result = "__lt__" and n = 1 + or + result = "__le__" and n = 2 + or + result = "__gt__" and n = 3 + or result = "__ge__" and n = 4 } @@ -32,8 +33,7 @@ predicate overrides_ordering_method(ClassValue c, string name) { ( c.declaresAttribute(name) or - exists(ClassValue sup | - sup = c.getASuperType() and not sup = Value::named("object") | + exists(ClassValue sup | sup = c.getASuperType() and not sup = Value::named("object") | sup.declaresAttribute(name) ) ) @@ -41,15 +41,14 @@ predicate overrides_ordering_method(ClassValue c, string name) { string unimplemented_ordering(ClassValue c, int n) { not c = Value::named("object") and - not overrides_ordering_method(c, result) and + not overrides_ordering_method(c, result) and result = ordering_name(n) } string unimplemented_ordering_methods(ClassValue c, int n) { n = 0 and result = "" and exists(unimplemented_ordering(c, _)) or - exists(string prefix, int nm1 | - n = nm1 + 1 and prefix = unimplemented_ordering_methods(c, nm1) | + exists(string prefix, int nm1 | n = nm1 + 1 and prefix = unimplemented_ordering_methods(c, nm1) | prefix = "" and result = unimplemented_ordering(c, n) or result = prefix and not exists(unimplemented_ordering(c, n)) and n < 5 @@ -60,16 +59,15 @@ string unimplemented_ordering_methods(ClassValue c, int n) { Value ordering_method(ClassValue c, string name) { /* If class doesn't declare a method then don't blame this class (the superclass will be blamed). */ - name = ordering_name(_) and result = c.declaredAttribute(name) + name = ordering_name(_) and result = c.declaredAttribute(name) } from ClassValue c, Value ordering, string name -where not c.failedInference(_) and -not total_ordering(c.getScope()) -and ordering = ordering_method(c, name) and -exists(unimplemented_ordering(c, _)) - -select c, "Class " + c.getName() + " implements $@, but does not implement " + unimplemented_ordering_methods(c, 4) + ".", -ordering, name - - +where + not c.failedInference(_) and + not total_ordering(c.getScope()) and + ordering = ordering_method(c, name) and + exists(unimplemented_ordering(c, _)) +select c, + "Class " + c.getName() + " implements $@, but does not implement " + + unimplemented_ordering_methods(c, 4) + ".", ordering, name diff --git a/python/ql/src/Classes/InconsistentMRO.ql b/python/ql/src/Classes/InconsistentMRO.ql index 08b1016086c..a9541bc9023 100644 --- a/python/ql/src/Classes/InconsistentMRO.ql +++ b/python/ql/src/Classes/InconsistentMRO.ql @@ -13,15 +13,18 @@ import python ClassObject left_base(ClassObject type, ClassObject base) { - exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i-1)) + exists(int i | i > 0 and type.getBaseType(i) = base and result = type.getBaseType(i - 1)) } predicate invalid_mro(ClassObject t, ClassObject left, ClassObject right) { t.isNewStyle() and - left = left_base(t, right) and left = right.getAnImproperSuperType() + left = left_base(t, right) and + left = right.getAnImproperSuperType() } from ClassObject t, ClassObject left, ClassObject right where invalid_mro(t, left, right) -select t, "Construction of class " + t.getName() + " can fail due to invalid method resolution order(MRO) for bases $@ and $@.", -left, left.getName(), right, right.getName() \ No newline at end of file +select t, + "Construction of class " + t.getName() + + " can fail due to invalid method resolution order(MRO) for bases $@ and $@.", left, + left.getName(), right, right.getName() diff --git a/python/ql/src/Classes/InitCallsSubclassMethod.ql b/python/ql/src/Classes/InitCallsSubclassMethod.ql index 5a191d861bf..b0e1cc0d8f0 100644 --- a/python/ql/src/Classes/InitCallsSubclassMethod.ql +++ b/python/ql/src/Classes/InitCallsSubclassMethod.ql @@ -13,23 +13,18 @@ import python - -from ClassObject supercls, string method, Call call, - FunctionObject overriding, FunctionObject overridden - +from + ClassObject supercls, string method, Call call, FunctionObject overriding, + FunctionObject overridden where -exists(FunctionObject init, SelfAttribute sa | - supercls.declaredAttribute("__init__") = init and - call.getScope() = init.getFunction() and call.getFunc() = sa | - sa.getName() = method and - overridden = supercls.declaredAttribute(method) and - overriding.overrides(overridden) -) - -select call, "Call to self.$@ in __init__ method, which is overridden by $@.", - overridden, method, - overriding, overriding.descriptiveString() - - - - + exists(FunctionObject init, SelfAttribute sa | + supercls.declaredAttribute("__init__") = init and + call.getScope() = init.getFunction() and + call.getFunc() = sa + | + sa.getName() = method and + overridden = supercls.declaredAttribute(method) and + overriding.overrides(overridden) + ) +select call, "Call to self.$@ in __init__ method, which is overridden by $@.", overridden, method, + overriding, overriding.descriptiveString() diff --git a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql index ec2e91987dd..ca8a260b863 100644 --- a/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql +++ b/python/ql/src/Classes/MaybeUndefinedClassAttribute.ql @@ -16,26 +16,29 @@ import ClassAttributes predicate guarded_by_other_attribute(SelfAttributeRead a, CheckClass c) { c.sometimesDefines(a.getName()) and - exists(SelfAttributeRead guard, If i | + exists(SelfAttributeRead guard, If i | i.contains(a) and - c.assignedInInit(guard.getName()) | + c.assignedInInit(guard.getName()) + | i.getTest() = guard or i.getTest().contains(guard) ) } - predicate maybe_undefined_class_attribute(SelfAttributeRead a, CheckClass c) { c.sometimesDefines(a.getName()) and not c.alwaysDefines(a.getName()) and - c.interestingUndefined(a) and + c.interestingUndefined(a) and not guarded_by_other_attribute(a, c) } from Attribute a, ClassObject c, SelfAttributeStore sa -where maybe_undefined_class_attribute(a, c) and -sa.getClass() = c.getPyClass() and sa.getName() = a.getName() -select a, "Attribute '" + a.getName() + -"' is not defined in the class body nor in the __init__() method, but it is defined $@", sa, "here" - +where + maybe_undefined_class_attribute(a, c) and + sa.getClass() = c.getPyClass() and + sa.getName() = a.getName() +select a, + "Attribute '" + a.getName() + + "' is not defined in the class body nor in the __init__() method, but it is defined $@", sa, + "here" diff --git a/python/ql/src/Classes/MethodCallOrder.qll b/python/ql/src/Classes/MethodCallOrder.qll index 2960d652052..494c234da3c 100644 --- a/python/ql/src/Classes/MethodCallOrder.qll +++ b/python/ql/src/Classes/MethodCallOrder.qll @@ -1,17 +1,20 @@ import python // Helper predicates for multiple call to __init__/__del__ queries. - -pragma [noinline] -private predicate multiple_invocation_paths_helper(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +pragma[noinline] +private predicate multiple_invocation_paths_helper( + FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi +) { i1 != i2 and i1 = top.getACallee+() and i2 = top.getACallee+() and i1.getFunction() = multi } -pragma [noinline] -private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +pragma[noinline] +private predicate multiple_invocation_paths( + FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi +) { multiple_invocation_paths_helper(top, i1, i2, multi) and i2.getFunction() = multi } @@ -21,7 +24,8 @@ predicate multiple_calls_to_superclass_method(ClassObject self, FunctionObject m exists(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2 | multiple_invocation_paths(top, i1, i2, multi) and top.runtime(self.declaredAttribute(name)) and - self.getASuperType().declaredAttribute(name) = multi | + self.getASuperType().declaredAttribute(name) = multi + | // Only called twice if called from different functions, // or if one call-site can reach the other. i1.getCall().getScope() != i2.getCall().getScope() @@ -53,7 +57,9 @@ private predicate missing_call(FunctionObject meth, string name) { } /** Holds if `self.name` does not call `missing`, even though it is expected to. */ -predicate missing_call_to_superclass_method(ClassObject self, FunctionObject top, FunctionObject missing, string name) { +predicate missing_call_to_superclass_method( + ClassObject self, FunctionObject top, FunctionObject missing, string name +) { missing = self.getASuperType().declaredAttribute(name) and top = self.lookupAttribute(name) and /* There is no call to missing originating from top */ @@ -63,10 +69,7 @@ predicate missing_call_to_superclass_method(ClassObject self, FunctionObject top sup = self.getAnImproperSuperType() and named_attributes_not_method(sup, name) ) and - not self.isAbstract() - and - does_something(missing) - and + not self.isAbstract() and + does_something(missing) and not missing_call(top, name) } - diff --git a/python/ql/src/Classes/MissingCallToDel.ql b/python/ql/src/Classes/MissingCallToDel.ql index d08c8399669..b54a9b8c782 100644 --- a/python/ql/src/Classes/MissingCallToDel.ql +++ b/python/ql/src/Classes/MissingCallToDel.ql @@ -13,14 +13,12 @@ import python import MethodCallOrder - from ClassObject self, FunctionObject missing - where missing_call_to_superclass_method(self, _, missing, "__del__") and not missing.neverReturns() and not self.failedInference() and not missing.isBuiltin() -select self, "Class " + self.getName() + " may not be cleaned up properly as $@ is not called during deletion.", -missing, missing.descriptiveString() - +select self, + "Class " + self.getName() + " may not be cleaned up properly as $@ is not called during deletion.", + missing, missing.descriptiveString() diff --git a/python/ql/src/Classes/MissingCallToInit.ql b/python/ql/src/Classes/MissingCallToInit.ql index ad137f817f4..bb6121e33b6 100644 --- a/python/ql/src/Classes/MissingCallToInit.ql +++ b/python/ql/src/Classes/MissingCallToInit.ql @@ -14,7 +14,6 @@ import python import MethodCallOrder from ClassObject self, FunctionObject initializer, FunctionObject missing - where self.lookupAttribute("__init__") = initializer and missing_call_to_superclass_method(self, initializer, missing, "__init__") and @@ -24,5 +23,6 @@ where not self.failedInference() and not missing.isBuiltin() and not self.isAbstract() -select self, "Class " + self.getName() + " may not be initialized properly as $@ is not called from its $@.", -missing, missing.descriptiveString(), initializer, "__init__ method" \ No newline at end of file +select self, + "Class " + self.getName() + " may not be initialized properly as $@ is not called from its $@.", + missing, missing.descriptiveString(), initializer, "__init__ method" diff --git a/python/ql/src/Classes/MutatingDescriptor.ql b/python/ql/src/Classes/MutatingDescriptor.ql index 65659526f57..1f1188c2830 100644 --- a/python/ql/src/Classes/MutatingDescriptor.ql +++ b/python/ql/src/Classes/MutatingDescriptor.ql @@ -15,8 +15,7 @@ import python predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { cls.isDescriptorType() and exists(PyFunctionObject f, PyFunctionObject get_set | - exists(string name | - cls.lookupAttribute(name) = get_set | + exists(string name | cls.lookupAttribute(name) = get_set | name = "__get__" or name = "__set__" or name = "__delete__" ) and cls.lookupAttribute(_) = f and @@ -27,7 +26,7 @@ predicate mutates_descriptor(ClassObject cls, SelfAttributeStore s) { } from ClassObject cls, SelfAttributeStore s -where -mutates_descriptor(cls, s) - -select s, "Mutation of descriptor $@ object may lead to action-at-a-distance effects or race conditions for properties.", cls, cls.getName() \ No newline at end of file +where mutates_descriptor(cls, s) +select s, + "Mutation of descriptor $@ object may lead to action-at-a-distance effects or race conditions for properties.", + cls, cls.getName() diff --git a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql index bd2be2ed379..168348e7b1c 100644 --- a/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql +++ b/python/ql/src/Classes/OverwritingAttributeInSuperClass.ql @@ -13,59 +13,80 @@ import python - class InitCallStmt extends ExprStmt { - InitCallStmt() { exists(Call call, Attribute attr | call = this.getValue() and attr = call.getFunc() | - attr.getName() = "__init__") + attr.getName() = "__init__" + ) } - } predicate overwrites_which(Function subinit, AssignStmt write_attr, string which) { - write_attr.getScope() = subinit and self_write_stmt(write_attr, _) and + write_attr.getScope() = subinit and + self_write_stmt(write_attr, _) and exists(Stmt top | top.contains(write_attr) or top = write_attr | - (exists(int i, int j, InitCallStmt call | call.getScope() = subinit | i > j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "superclass") - or - exists(int i, int j, InitCallStmt call | call.getScope() = subinit | i < j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "subclass") - ) - ) + ( + exists(int i, int j, InitCallStmt call | call.getScope() = subinit | + i > j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "superclass" + ) + or + exists(int i, int j, InitCallStmt call | call.getScope() = subinit | + i < j and top = subinit.getStmt(i) and call = subinit.getStmt(j) and which = "subclass" + ) + ) + ) } predicate self_write_stmt(Stmt s, string attr) { - exists(Attribute a, Name self | self = a.getObject() and s.contains(a) and self.getId() = "self" and a.getCtx() instanceof Store and a.getName() = attr) + exists(Attribute a, Name self | + self = a.getObject() and + s.contains(a) and + self.getId() = "self" and + a.getCtx() instanceof Store and + a.getName() = attr + ) } predicate both_assign_attribute(Stmt s1, Stmt s2, Function f1, Function f2) { - exists(string name | s1.getScope() = f1 and s2.getScope() = f2 and self_write_stmt(s1, name) and self_write_stmt(s2, name)) + exists(string name | + s1.getScope() = f1 and + s2.getScope() = f2 and + self_write_stmt(s1, name) and + self_write_stmt(s2, name) + ) } -predicate attribute_overwritten(AssignStmt overwrites, AssignStmt overwritten, string name, string classtype, string classname) -{ - exists(FunctionObject superinit, FunctionObject subinit, ClassObject superclass, ClassObject subclass, AssignStmt subattr, AssignStmt superattr | - (classtype = "superclass" and classname = superclass.getName() and overwrites = subattr and overwritten = superattr or - classtype = "subclass" and classname = subclass.getName() and overwrites = superattr and overwritten = subattr) - and - /* OK if overwritten in subclass and is a class attribute */ - (not exists(superclass.declaredAttribute(name)) or classtype = "subclass") - and - superclass.declaredAttribute("__init__") = superinit - and - subclass.declaredAttribute("__init__") = subinit - and - superclass = subclass.getASuperType() - and - overwrites_which(subinit.getFunction(), subattr, classtype) - and - both_assign_attribute(subattr, superattr, subinit.getFunction(), superinit.getFunction()) - and - self_write_stmt(superattr, name) - ) +predicate attribute_overwritten( + AssignStmt overwrites, AssignStmt overwritten, string name, string classtype, string classname +) { + exists( + FunctionObject superinit, FunctionObject subinit, ClassObject superclass, ClassObject subclass, + AssignStmt subattr, AssignStmt superattr + | + ( + classtype = "superclass" and + classname = superclass.getName() and + overwrites = subattr and + overwritten = superattr + or + classtype = "subclass" and + classname = subclass.getName() and + overwrites = superattr and + overwritten = subattr + ) and + /* OK if overwritten in subclass and is a class attribute */ + (not exists(superclass.declaredAttribute(name)) or classtype = "subclass") and + superclass.declaredAttribute("__init__") = superinit and + subclass.declaredAttribute("__init__") = subinit and + superclass = subclass.getASuperType() and + overwrites_which(subinit.getFunction(), subattr, classtype) and + both_assign_attribute(subattr, superattr, subinit.getFunction(), superinit.getFunction()) and + self_write_stmt(superattr, name) + ) } - from string classtype, AssignStmt overwrites, AssignStmt overwritten, string name, string classname where attribute_overwritten(overwrites, overwritten, name, classtype, classname) - -select overwrites, "Assignment overwrites attribute " + name + ", which was previously defined in " + classtype + " $@.", overwritten, classname +select overwrites, + "Assignment overwrites attribute " + name + ", which was previously defined in " + classtype + + " $@.", overwritten, classname diff --git a/python/ql/src/Classes/PropertyInOldStyleClass.ql b/python/ql/src/Classes/PropertyInOldStyleClass.ql index fb2c822a573..ff2bf13a9f8 100644 --- a/python/ql/src/Classes/PropertyInOldStyleClass.ql +++ b/python/ql/src/Classes/PropertyInOldStyleClass.ql @@ -14,4 +14,6 @@ import python from PropertyObject prop, ClassObject cls where cls.declaredAttribute(_) = prop and not cls.failedInference() and not cls.isNewStyle() -select prop, "Property " + prop.getName() + " will not work properly, as class " + cls.getName() + " is an old-style class." +select prop, + "Property " + prop.getName() + " will not work properly, as class " + cls.getName() + + " is an old-style class." diff --git a/python/ql/src/Classes/ShouldBeContextManager.ql b/python/ql/src/Classes/ShouldBeContextManager.ql index d7394728935..e6bf946b65a 100644 --- a/python/ql/src/Classes/ShouldBeContextManager.ql +++ b/python/ql/src/Classes/ShouldBeContextManager.ql @@ -16,4 +16,6 @@ import python from ClassObject c where not c.isC() and not c.isContextManager() and exists(c.declaredAttribute("__del__")) -select c, "Class " + c.getName() + " implements __del__ (presumably to release some resource). Consider making it a context manager." +select c, + "Class " + c.getName() + + " implements __del__ (presumably to release some resource). Consider making it a context manager." diff --git a/python/ql/src/Classes/SubclassShadowing.ql b/python/ql/src/Classes/SubclassShadowing.ql index 6cdd9edf01d..ed1a79869b0 100644 --- a/python/ql/src/Classes/SubclassShadowing.ql +++ b/python/ql/src/Classes/SubclassShadowing.ql @@ -11,30 +11,36 @@ * @id py/attribute-shadows-method */ -/* Determine if a class defines a method that is shadowed by an attribute - defined in a super-class -*/ +/* + * Determine if a class defines a method that is shadowed by an attribute + * defined in a super-class + */ /* Need to find attributes defined in superclass (only in __init__?) */ - import python -predicate shadowed_by_super_class(ClassObject c, ClassObject supercls, Assign assign, FunctionObject f) -{ - c.getASuperType() = supercls and c.declaredAttribute(_) = f and +predicate shadowed_by_super_class( + ClassObject c, ClassObject supercls, Assign assign, FunctionObject f +) { + c.getASuperType() = supercls and + c.declaredAttribute(_) = f and exists(FunctionObject init, Attribute attr | supercls.declaredAttribute("__init__") = init and attr = assign.getATarget() and - ((Name)attr.getObject()).getId() = "self" and + attr.getObject().(Name).getId() = "self" and attr.getName() = f.getName() and - assign.getScope() = ((FunctionExpr)init.getOrigin()).getInnerScope() + assign.getScope() = init.getOrigin().(FunctionExpr).getInnerScope() ) and - /* It's OK if the super class defines the method as well. - * We assume that the original method must have been defined for a reason. */ + /* + * It's OK if the super class defines the method as well. + * We assume that the original method must have been defined for a reason. + */ + not supercls.hasAttribute(f.getName()) } from ClassObject c, ClassObject supercls, Assign assign, FunctionObject shadowed where shadowed_by_super_class(c, supercls, assign, shadowed) -select shadowed.getOrigin(), "Method " + shadowed.getName() + " is shadowed by $@ in super class '"+ supercls.getName() + "'.", assign, "an attribute" - +select shadowed.getOrigin(), + "Method " + shadowed.getName() + " is shadowed by $@ in super class '" + supercls.getName() + "'.", + assign, "an attribute" diff --git a/python/ql/src/Classes/SuperInOldStyleClass.ql b/python/ql/src/Classes/SuperInOldStyleClass.ql index b6c7649a1ca..aa4c62c6f08 100644 --- a/python/ql/src/Classes/SuperInOldStyleClass.ql +++ b/python/ql/src/Classes/SuperInOldStyleClass.ql @@ -13,10 +13,15 @@ import python predicate uses_of_super_in_old_style_class(Call s) { - exists(Function f, ClassObject c | s.getScope() = f and f.getScope() = c.getPyClass() and not c.failedInference() and - not c.isNewStyle() and ((Name)s.getFunc()).getId() = "super") + exists(Function f, ClassObject c | + s.getScope() = f and + f.getScope() = c.getPyClass() and + not c.failedInference() and + not c.isNewStyle() and + s.getFunc().(Name).getId() = "super" + ) } from Call c where uses_of_super_in_old_style_class(c) -select c, "super() will not work in old-style classes" \ No newline at end of file +select c, "super() will not work in old-style classes" diff --git a/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql b/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql index b0e4a13469d..cd4c74a5e86 100644 --- a/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql +++ b/python/ql/src/Classes/SuperclassDelCalledMultipleTimes.ql @@ -13,15 +13,16 @@ import python import MethodCallOrder - from ClassObject self, FunctionObject multi -where -multiple_calls_to_superclass_method(self, multi, "__del__") and -not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__del__") and -not exists(FunctionObject better | - multiple_calls_to_superclass_method(self, better, "__del__") and - better.overrides(multi) -) and -not self.failedInference() -select self, "Class " + self.getName() + " may not be cleaned up properly as $@ may be called multiple times during destruction.", -multi, multi.descriptiveString() +where + multiple_calls_to_superclass_method(self, multi, "__del__") and + not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__del__") and + not exists(FunctionObject better | + multiple_calls_to_superclass_method(self, better, "__del__") and + better.overrides(multi) + ) and + not self.failedInference() +select self, + "Class " + self.getName() + + " may not be cleaned up properly as $@ may be called multiple times during destruction.", multi, + multi.descriptiveString() diff --git a/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql b/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql index 723527e1de8..71d05533fde 100644 --- a/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql +++ b/python/ql/src/Classes/SuperclassInitCalledMultipleTimes.ql @@ -14,13 +14,16 @@ import python import MethodCallOrder from ClassObject self, FunctionObject multi -where multi != theObjectType().lookupAttribute("__init__") and -multiple_calls_to_superclass_method(self, multi, "__init__") and -not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__init__") and -not exists(FunctionObject better | - multiple_calls_to_superclass_method(self, better, "__init__") and - better.overrides(multi) -) and -not self.failedInference() -select self, "Class " + self.getName() + " may not be initialized properly as $@ may be called multiple times during initialization.", -multi, multi.descriptiveString() +where + multi != theObjectType().lookupAttribute("__init__") and + multiple_calls_to_superclass_method(self, multi, "__init__") and + not multiple_calls_to_superclass_method(self.getABaseType(), multi, "__init__") and + not exists(FunctionObject better | + multiple_calls_to_superclass_method(self, better, "__init__") and + better.overrides(multi) + ) and + not self.failedInference() +select self, + "Class " + self.getName() + + " may not be initialized properly as $@ may be called multiple times during initialization.", + multi, multi.descriptiveString() diff --git a/python/ql/src/Classes/UndefinedClassAttribute.ql b/python/ql/src/Classes/UndefinedClassAttribute.ql index 6619fd031eb..bdbbcbf2496 100644 --- a/python/ql/src/Classes/UndefinedClassAttribute.ql +++ b/python/ql/src/Classes/UndefinedClassAttribute.ql @@ -32,4 +32,3 @@ predicate report_undefined_class_attribute(Attribute a, ClassObject c, string na from Attribute a, ClassObject c, string name where report_undefined_class_attribute(a, c, name) select a, "Attribute '" + name + "' is not defined in either the class body or in any method" - diff --git a/python/ql/src/Classes/UselessClass.ql b/python/ql/src/Classes/UselessClass.ql index e04ea103ad6..e4e3f31f3a2 100644 --- a/python/ql/src/Classes/UselessClass.ql +++ b/python/ql/src/Classes/UselessClass.ql @@ -21,63 +21,68 @@ predicate does_not_define_special_method(Class cls) { not exists(Function f | f = cls.getAMethod() and f.isSpecialMethod()) } - predicate no_inheritance(Class c) { - not exists(ClassObject cls, ClassObject other | - cls.getPyClass() = c and - other != theObjectType() | + not exists(ClassValue cls, ClassValue other | + cls.getScope() = c and + other != ClassValue::object() + | other.getABaseType() = cls or cls.getABaseType() = other - ) - and + ) and not exists(Expr base | base = c.getABase() | - not base instanceof Name or ((Name)base).getId() != "object" + not base instanceof Name or base.(Name).getId() != "object" ) } -predicate is_decorated(Class c) { - exists(c.getADecorator()) -} +predicate is_decorated(Class c) { exists(c.getADecorator()) } predicate is_stateful(Class c) { - exists(Function method, ExprContext ctx | - method.getScope() = c and (ctx instanceof Store or ctx instanceof AugStore) | + exists(Function method, ExprContext ctx | + method.getScope() = c and + (ctx instanceof Store or ctx instanceof AugStore) + | exists(Subscript s | s.getScope() = method and s.getCtx() = ctx) or exists(Attribute a | a.getScope() = method and a.getCtx() = ctx) ) or - exists(Function method, Call call, Attribute a, string name | - method.getScope() = c and call.getScope() = method and - call.getFunc() = a and a.getName() = name | - name = "pop" or name = "remove" or name = "discard" or - name = "extend" or name = "append" + exists(Function method, Call call, Attribute a, string name | + method.getScope() = c and + call.getScope() = method and + call.getFunc() = a and + a.getName() = name + | + name = "pop" or + name = "remove" or + name = "discard" or + name = "extend" or + name = "append" ) - } predicate useless_class(Class c, int methods) { - c.isTopLevel() - and - c.isPublic() - and - no_inheritance(c) - and - fewer_than_two_public_methods(c, methods) - and - does_not_define_special_method(c) - and - not c.isProbableMixin() - and - not is_decorated(c) - and + c.isTopLevel() and + c.isPublic() and + no_inheritance(c) and + fewer_than_two_public_methods(c, methods) and + does_not_define_special_method(c) and + not c.isProbableMixin() and + not is_decorated(c) and not is_stateful(c) } from Class c, int methods, string msg -where useless_class(c, methods) and -(methods = 1 and msg = "Class " + c.getName() + " defines only one public method, which should be replaced by a function." - or - methods = 0 and msg = "Class " + c.getName() + " defines no public methods and could be replaced with a namedtuple or dictionary." -) +where + useless_class(c, methods) and + ( + methods = 1 and + msg = + "Class " + c.getName() + + " defines only one public method, which should be replaced by a function." + or + methods = 0 and + msg = + "Class " + c.getName() + + " defines no public methods and could be replaced with a namedtuple or dictionary." + ) select c, msg diff --git a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql index 022d6a515e6..f3276ac61ef 100644 --- a/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNameForArgumentInClassInstantiation.ql @@ -14,14 +14,11 @@ */ import python - import Expressions.CallArgs - -from Call call, ClassObject cls, string name, FunctionObject init +from Call call, ClassValue cls, string name, FunctionValue init where - illegally_named_parameter_objectapi(call, cls, name) - and init = get_function_or_initializer_objectapi(cls) -select - call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init, init.getQualifiedName() - + illegally_named_parameter(call, cls, name) and + init = get_function_or_initializer(cls) +select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", init, + init.getQualifiedName() diff --git a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql index f94b5ac5b3e..c8763bd8aa7 100644 --- a/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql +++ b/python/ql/src/Classes/WrongNumberArgumentsInClassInstantiation.ql @@ -15,11 +15,17 @@ import python import Expressions.CallArgs -from Call call, ClassObject cls, string too, string should, int limit, FunctionObject init +from Call call, ClassValue cls, string too, string should, int limit, FunctionValue init where -( - too_many_args_objectapi(call, cls, limit) and too = "too many arguments" and should = "no more than " - or - too_few_args_objectapi(call, cls, limit) and too = "too few arguments" and should = "no fewer than " -) and init = get_function_or_initializer_objectapi(cls) -select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init, init.getQualifiedName() + ( + too_many_args(call, cls, limit) and + too = "too many arguments" and + should = "no more than " + or + too_few_args(call, cls, limit) and + too = "too few arguments" and + should = "no fewer than " + ) and + init = get_function_or_initializer(cls) +select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", init, + init.getQualifiedName() diff --git a/python/ql/src/Exceptions/CatchingBaseException.ql b/python/ql/src/Exceptions/CatchingBaseException.ql index d175297f1c9..04a95a8e827 100644 --- a/python/ql/src/Exceptions/CatchingBaseException.ql +++ b/python/ql/src/Exceptions/CatchingBaseException.ql @@ -14,17 +14,16 @@ import python -predicate doesnt_reraise(ExceptStmt ex) { - ex.getAFlowNode().getBasicBlock().reachesExit() -} +predicate doesnt_reraise(ExceptStmt ex) { ex.getAFlowNode().getBasicBlock().reachesExit() } predicate catches_base_exception(ExceptStmt ex) { - ex.getType().pointsTo(ClassValue::baseException()) - or - not exists(ex.getType()) + ex.getType().pointsTo(ClassValue::baseException()) + or + not exists(ex.getType()) } from ExceptStmt ex -where catches_base_exception(ex) and -doesnt_reraise(ex) +where + catches_base_exception(ex) and + doesnt_reraise(ex) select ex, "Except block directly handles BaseException." diff --git a/python/ql/src/Exceptions/EmptyExcept.ql b/python/ql/src/Exceptions/EmptyExcept.ql index a753181af71..fd656755c1c 100755 --- a/python/ql/src/Exceptions/EmptyExcept.ql +++ b/python/ql/src/Exceptions/EmptyExcept.ql @@ -13,21 +13,18 @@ import python -predicate -empty_except(ExceptStmt ex) { +predicate empty_except(ExceptStmt ex) { not exists(Stmt s | s = ex.getAStmt() and not s instanceof Pass) } -predicate no_else(ExceptStmt ex) { - not exists(ex.getTry().getOrelse()) -} +predicate no_else(ExceptStmt ex) { not exists(ex.getTry().getOrelse()) } predicate no_comment(ExceptStmt ex) { - not exists(Comment c | - c.getLocation().getFile() = ex.getLocation().getFile() and - c.getLocation().getStartLine() >= ex.getLocation().getStartLine() and - c.getLocation().getEndLine() <= ex.getBody().getLastItem().getLocation().getEndLine() - ) + not exists(Comment c | + c.getLocation().getFile() = ex.getLocation().getFile() and + c.getLocation().getStartLine() >= ex.getLocation().getStartLine() and + c.getLocation().getEndLine() <= ex.getBody().getLastItem().getLocation().getEndLine() + ) } predicate non_local_control_flow(ExceptStmt ex) { @@ -38,7 +35,8 @@ predicate try_has_normal_exit(Try try) { exists(ControlFlowNode pred, ControlFlowNode succ | /* Exists a non-exception predecessor, successor pair */ pred.getASuccessor() = succ and - not pred.getAnExceptionalSuccessor() = succ | + not pred.getAnExceptionalSuccessor() = succ + | /* Successor is either a normal flow node or a fall-through exit */ not exists(Scope s | s.getReturnNode() = succ) and /* Predecessor is in try body and successor is not */ @@ -50,8 +48,7 @@ predicate try_has_normal_exit(Try try) { predicate attribute_access(Stmt s) { s.(ExprStmt).getValue() instanceof Attribute or - exists(string name | - s.(ExprStmt).getValue().(Call).getFunc().(Name).getId() = name | + exists(string name | s.(ExprStmt).getValue().(Call).getFunc().(Name).getId() = name | name = "getattr" or name = "setattr" or name = "delattr" ) or @@ -65,8 +62,7 @@ predicate subscript(Stmt s) { } predicate encode_decode(Call ex, ClassValue type) { - exists(string name | - ex.getFunc().(Attribute).getName() = name | + exists(string name | ex.getFunc().(Attribute).getName() = name | name = "encode" and type = ClassValue::unicodeEncodeError() or name = "decode" and type = ClassValue::unicodeDecodeError() @@ -80,8 +76,7 @@ predicate small_handler(ExceptStmt ex, Stmt s, ClassValue type) { } predicate focussed_handler(ExceptStmt ex) { - exists(Stmt s, ClassValue type | - small_handler(ex, s, type) | + exists(Stmt s, ClassValue type | small_handler(ex, s, type) | subscript(s) and type.getASuperType() = ClassValue::lookupError() or attribute_access(s) and type = ClassValue::attributeError() @@ -92,12 +87,15 @@ predicate focussed_handler(ExceptStmt ex) { ) } -Try try_return() { - not exists(result.getStmt(1)) and result.getStmt(0) instanceof Return -} +Try try_return() { not exists(result.getStmt(1)) and result.getStmt(0) instanceof Return } from ExceptStmt ex -where empty_except(ex) and no_else(ex) and no_comment(ex) and not non_local_control_flow(ex) - and not ex.getTry() = try_return() and try_has_normal_exit(ex.getTry()) and - not focussed_handler(ex) +where + empty_except(ex) and + no_else(ex) and + no_comment(ex) and + not non_local_control_flow(ex) and + not ex.getTry() = try_return() and + try_has_normal_exit(ex.getTry()) and + not focussed_handler(ex) select ex, "'except' clause does nothing but pass and there is no explanatory comment." diff --git a/python/ql/src/Exceptions/IllegalRaise.ql b/python/ql/src/Exceptions/IllegalRaise.ql index da1bc56ae33..f05f5437db2 100644 --- a/python/ql/src/Exceptions/IllegalRaise.ql +++ b/python/ql/src/Exceptions/IllegalRaise.ql @@ -16,6 +16,10 @@ import Raising import Exceptions.NotImplemented from Raise r, ClassValue t -where type_or_typeof(r, t, _) and not t.isLegalExceptionType() and not t.failedInference(_) and not use_of_not_implemented_in_raise(r, _) -select r, "Illegal class '" + t.getName() + "' raised; will result in a TypeError being raised instead." - +where + type_or_typeof(r, t, _) and + not t.isLegalExceptionType() and + not t.failedInference(_) and + not use_of_not_implemented_in_raise(r, _) +select r, + "Illegal class '" + t.getName() + "' raised; will result in a TypeError being raised instead." diff --git a/python/ql/src/Exceptions/NotImplemented.qll b/python/ql/src/Exceptions/NotImplemented.qll index 09b3c37998b..b319311290e 100644 --- a/python/ql/src/Exceptions/NotImplemented.qll +++ b/python/ql/src/Exceptions/NotImplemented.qll @@ -1,4 +1,3 @@ - import python /** Holds if `notimpl` refers to `NotImplemented` or `NotImplemented()` in the `raise` statement */ diff --git a/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql b/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql index 89f1bb04568..933d15ddf60 100644 --- a/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql +++ b/python/ql/src/Exceptions/NotImplementedIsNotAnException.ql @@ -15,5 +15,4 @@ import Exceptions.NotImplemented from Expr notimpl where use_of_not_implemented_in_raise(_, notimpl) - select notimpl, "NotImplemented is not an Exception. Did you mean NotImplementedError?" diff --git a/python/ql/src/Exceptions/Raising.qll b/python/ql/src/Exceptions/Raising.qll index 7e53c0bbd27..ad98c93d0c4 100644 --- a/python/ql/src/Exceptions/Raising.qll +++ b/python/ql/src/Exceptions/Raising.qll @@ -1,16 +1,12 @@ import python -/** Whether the raise statement 'r' raises 'type' from origin 'orig' */ +/** Whether the raise statement 'r' raises 'type' from origin 'orig' */ predicate type_or_typeof(Raise r, ClassValue type, AstNode orig) { - exists(Expr exception | - exception = r.getRaised() | + exists(Expr exception | exception = r.getRaised() | exception.pointsTo(type, orig) or not exists(ClassValue exc_type | exception.pointsTo(exc_type)) and not type = ClassValue::type() and // First value is an unknown exception type - exists(Value val | exception.pointsTo(val, orig) | - val.getClass() = type - ) + exists(Value val | exception.pointsTo(val, orig) | val.getClass() = type) ) - } diff --git a/python/ql/src/Exceptions/RaisingTuple.ql b/python/ql/src/Exceptions/RaisingTuple.ql index ab197fe1665..dc4b295a90d 100644 --- a/python/ql/src/Exceptions/RaisingTuple.ql +++ b/python/ql/src/Exceptions/RaisingTuple.ql @@ -12,8 +12,11 @@ import python from Raise r, Value v, AstNode origin -where r.getException().pointsTo(v, origin) and -v.getClass() = ClassValue::tuple() and -major_version() = 2 /* Raising a tuple is a type error in Python 3, so is handled by the IllegalRaise query. */ - -select r, "Raising $@ will result in the first element (recursively) being raised and all other elements being discarded.", origin, "a tuple" \ No newline at end of file +where + r.getException().pointsTo(v, origin) and + v.getClass() = ClassValue::tuple() and + major_version() = 2 +/* Raising a tuple is a type error in Python 3, so is handled by the IllegalRaise query. */ +select r, + "Raising $@ will result in the first element (recursively) being raised and all other elements being discarded.", + origin, "a tuple" diff --git a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql index ff0f53dea4d..c2435d41b3e 100755 --- a/python/ql/src/Exceptions/UnguardedNextInGenerator.ql +++ b/python/ql/src/Exceptions/UnguardedNextInGenerator.ql @@ -12,13 +12,9 @@ import python -FunctionValue iter() { - result = Value::named("iter") -} +FunctionValue iter() { result = Value::named("iter") } -BuiltinFunctionValue next() { - result = Value::named("next") -} +BuiltinFunctionValue next() { result = Value::named("next") } predicate call_to_iter(CallNode call, EssaVariable sequence) { sequence.getAUse() = iter().getArgumentForCall(call, 0) @@ -52,14 +48,14 @@ predicate stop_iteration_handled(CallNode call) { } from CallNode call -where call_to_next(call, _) and -not call_to_next_has_default(call) and -not exists(EssaVariable iterator | - call_to_next(call, iterator.getAUse()) and - iter_not_exhausted(iterator) -) and -call.getNode().getScope().(Function).isGenerator() and -not exists(Comp comp | comp.contains(call.getNode())) and -not stop_iteration_handled(call) - +where + call_to_next(call, _) and + not call_to_next_has_default(call) and + not exists(EssaVariable iterator | + call_to_next(call, iterator.getAUse()) and + iter_not_exhausted(iterator) + ) and + call.getNode().getScope().(Function).isGenerator() and + not exists(Comp comp | comp.contains(call.getNode())) and + not stop_iteration_handled(call) select call, "Call to next() in a generator" diff --git a/python/ql/src/Expressions/CallArgs.qll b/python/ql/src/Expressions/CallArgs.qll index e362256fd36..6d9baf6223d 100644 --- a/python/ql/src/Expressions/CallArgs.qll +++ b/python/ql/src/Expressions/CallArgs.qll @@ -1,14 +1,10 @@ import python - import Testing.Mox private int varargs_length_objectapi(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleObject t | - call.getStarargs().refersTo(t) | - result = t.getLength() - ) + exists(TupleObject t | call.getStarargs().refersTo(t) | result = t.getLength()) or result = count(call.getStarargs().(List).getAnElt()) } @@ -16,10 +12,7 @@ private int varargs_length_objectapi(Call call) { private int varargs_length(Call call) { not exists(call.getStarargs()) and result = 0 or - exists(TupleValue t | - call.getStarargs().pointsTo(t) | - result = t.length() - ) + exists(TupleValue t | call.getStarargs().pointsTo(t) | result = t.length()) or result = count(call.getStarargs().(List).getAnElt()) } @@ -38,43 +31,43 @@ private Keyword not_keyword_only_arg(Call call, FunctionValue func) { not func.getScope().getAKeywordOnlyArg().getId() = result.getArg() } -/** Gets the count of arguments that are passed as positional parameters even if they +/** + * Gets the count of arguments that are passed as positional parameters even if they * are named in the call. * This is the sum of the number of positional arguments, the number of elements in any explicit tuple passed as *arg * plus the number of keyword arguments that do not match keyword-only arguments (if the function does not take **kwargs). */ - private int positional_arg_count_for_call_objectapi(Call call, Object callable) { call = get_a_call_objectapi(callable).getNode() and exists(int positional_keywords | - exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | - not func.getFunction().hasKwArg() and - positional_keywords = count(not_keyword_only_arg_objectapi(call, func)) - or - func.getFunction().hasKwArg() and positional_keywords = 0 - ) - | - result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords + exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | + not func.getFunction().hasKwArg() and + positional_keywords = count(not_keyword_only_arg_objectapi(call, func)) + or + func.getFunction().hasKwArg() and positional_keywords = 0 + ) + | + result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords ) } -/** Gets the count of arguments that are passed as positional parameters even if they +/** + * Gets the count of arguments that are passed as positional parameters even if they * are named in the call. * This is the sum of the number of positional arguments, the number of elements in any explicit tuple passed as *arg * plus the number of keyword arguments that do not match keyword-only arguments (if the function does not take **kwargs). */ - private int positional_arg_count_for_call(Call call, Value callable) { call = get_a_call(callable).getNode() and exists(int positional_keywords | - exists(FunctionValue func | func = get_function_or_initializer(callable) | - not func.getScope().hasKwArg() and - positional_keywords = count(not_keyword_only_arg(call, func)) - or - func.getScope().hasKwArg() and positional_keywords = 0 - ) - | - result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords + exists(FunctionValue func | func = get_function_or_initializer(callable) | + not func.getScope().hasKwArg() and + positional_keywords = count(not_keyword_only_arg(call, func)) + or + func.getScope().hasKwArg() and positional_keywords = 0 + ) + | + result = count(call.getAnArg()) + varargs_length_objectapi(call) + positional_keywords ) } @@ -88,33 +81,32 @@ int arg_count(Call call) { /* Gets a call corresponding to the given class or function*/ private ControlFlowNode get_a_call_objectapi(Object callable) { - result = callable.(ClassObject).getACall() - or - result = callable.(FunctionObject).getACall() + result = callable.(ClassObject).getACall() + or + result = callable.(FunctionObject).getACall() } /* Gets a call corresponding to the given class or function*/ private ControlFlowNode get_a_call(Value callable) { - result = callable.(ClassValue).getACall() - or - result = callable.(FunctionValue).getACall() + result = callable.(ClassValue).getACall() + or + result = callable.(FunctionValue).getACall() } /* Gets the function object corresponding to the given class or function*/ FunctionObject get_function_or_initializer_objectapi(Object func_or_cls) { - result = func_or_cls.(FunctionObject) - or - result = func_or_cls.(ClassObject).declaredAttribute("__init__") + result = func_or_cls.(FunctionObject) + or + result = func_or_cls.(ClassObject).declaredAttribute("__init__") } /* Gets the function object corresponding to the given class or function*/ FunctionValue get_function_or_initializer(Value func_or_cls) { - result = func_or_cls.(FunctionValue) - or - result = func_or_cls.(ClassValue).declaredAttribute("__init__") + result = func_or_cls.(FunctionValue) + or + result = func_or_cls.(ClassValue).declaredAttribute("__init__") } - /**Whether there is an illegally named parameter called `name` in the `call` to `func` */ predicate illegally_named_parameter_objectapi(Call call, Object func, string name) { not func.isC() and @@ -135,19 +127,22 @@ predicate illegally_named_parameter(Call call, Value func, string name) { predicate too_few_args_objectapi(Call call, Object callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter_objectapi(call, callable, _) and - not exists(call.getStarargs()) and not exists(call.getKwargs()) and + not exists(call.getStarargs()) and + not exists(call.getKwargs()) and arg_count_objectapi(call) < limit and exists(FunctionObject func | func = get_function_or_initializer_objectapi(callable) | - call = func.getAFunctionCall().getNode() and limit = func.minParameters() and - // The combination of misuse of `mox.Mox().StubOutWithMock()` - // and a bug in mox's implementation of methods results in having to - // pass 1 too few arguments to the mocked function. - not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) - or - call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1 - or - callable instanceof ClassObject and - call.getAFlowNode() = get_a_call_objectapi(callable) and limit = func.minParameters() - 1 + call = func.getAFunctionCall().getNode() and + limit = func.minParameters() and + // The combination of misuse of `mox.Mox().StubOutWithMock()` + // and a bug in mox's implementation of methods results in having to + // pass 1 too few arguments to the mocked function. + not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) + or + call = func.getAMethodCall().getNode() and limit = func.minParameters() - 1 + or + callable instanceof ClassObject and + call.getAFlowNode() = get_a_call_objectapi(callable) and + limit = func.minParameters() - 1 ) } @@ -155,19 +150,22 @@ predicate too_few_args_objectapi(Call call, Object callable, int limit) { predicate too_few_args(Call call, Value callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter(call, callable, _) and - not exists(call.getStarargs()) and not exists(call.getKwargs()) and + not exists(call.getStarargs()) and + not exists(call.getKwargs()) and arg_count(call) < limit and exists(FunctionValue func | func = get_function_or_initializer(callable) | - call = func.getACall().getNode() and limit = func.minParameters() and - // The combination of misuse of `mox.Mox().StubOutWithMock()` - // and a bug in mox's implementation of methods results in having to - // pass 1 too few arguments to the mocked function. - not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) - or - call = func.getACall().getNode() and limit = func.minParameters() - 1 - or - callable instanceof ClassValue and - call.getAFlowNode() = get_a_call(callable) and limit = func.minParameters() - 1 + call = func.getACall().getNode() and + limit = func.minParameters() and + // The combination of misuse of `mox.Mox().StubOutWithMock()` + // and a bug in mox's implementation of methods results in having to + // pass 1 too few arguments to the mocked function. + not (useOfMoxInModule(call.getEnclosingModule()) and func.isNormalMethod()) + or + call = func.getACall().getNode() and limit = func.minParameters() - 1 + or + callable instanceof ClassValue and + call.getAFlowNode() = get_a_call(callable) and + limit = func.minParameters() - 1 ) } @@ -175,16 +173,18 @@ predicate too_few_args(Call call, Value callable, int limit) { predicate too_many_args_objectapi(Call call, Object callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter_objectapi(call, callable, _) and - exists(FunctionObject func | - func = get_function_or_initializer_objectapi(callable) and - not func.getFunction().hasVarArg() and limit >= 0 - | + exists(FunctionObject func | + func = get_function_or_initializer_objectapi(callable) and + not func.getFunction().hasVarArg() and + limit >= 0 + | call = func.getAFunctionCall().getNode() and limit = func.maxParameters() - or + or call = func.getAMethodCall().getNode() and limit = func.maxParameters() - 1 - or + or callable instanceof ClassObject and - call.getAFlowNode() = get_a_call_objectapi(callable) and limit = func.maxParameters() - 1 + call.getAFlowNode() = get_a_call_objectapi(callable) and + limit = func.maxParameters() - 1 ) and positional_arg_count_for_call_objectapi(call, callable) > limit } @@ -193,16 +193,18 @@ predicate too_many_args_objectapi(Call call, Object callable, int limit) { predicate too_many_args(Call call, Value callable, int limit) { // Exclude cases where an incorrect name is used as that is covered by 'Wrong name for an argument in a call' not illegally_named_parameter(call, callable, _) and - exists(FunctionValue func | - func = get_function_or_initializer(callable) and - not func.getScope().hasVarArg() and limit >= 0 - | + exists(FunctionValue func | + func = get_function_or_initializer(callable) and + not func.getScope().hasVarArg() and + limit >= 0 + | call = func.getACall().getNode() and limit = func.maxParameters() - or + or call = func.getACall().getNode() and limit = func.maxParameters() - 1 - or + or callable instanceof ClassValue and - call.getAFlowNode() = get_a_call(callable) and limit = func.maxParameters() - 1 + call.getAFlowNode() = get_a_call(callable) and + limit = func.maxParameters() - 1 ) and positional_arg_count_for_call(call, callable) > limit } @@ -221,35 +223,34 @@ predicate wrong_args(Call call, FunctionValue func, int limit, string too) { too_many_args(call, func, limit) and too = "too many" } -/** Holds if `call` has correct number of arguments for `func`. +/** + * Holds if `call` has correct number of arguments for `func`. * Implies nothing about whether `call` could call `func`. */ - bindingset[call, func] +bindingset[call, func] predicate correct_args_if_called_as_method_objectapi(Call call, FunctionObject func) { - arg_count_objectapi(call)+1 >= func.minParameters() - and + arg_count_objectapi(call) + 1 >= func.minParameters() and arg_count_objectapi(call) < func.maxParameters() } -/** Holds if `call` has correct number of arguments for `func`. +/** + * Holds if `call` has correct number of arguments for `func`. * Implies nothing about whether `call` could call `func`. */ - bindingset[call, func] +bindingset[call, func] predicate correct_args_if_called_as_method(Call call, FunctionValue func) { - arg_count(call)+1 >= func.minParameters() - and + arg_count(call) + 1 >= func.minParameters() and arg_count(call) < func.maxParameters() } /** Holds if `call` is a call to `overriding`, which overrides `func`. */ -predicate overridden_call_objectapi(FunctionObject func, FunctionObject overriding, Call call) { +predicate overridden_call_objectapi(FunctionObject func, FunctionObject overriding, Call call) { overriding.overrides(func) and overriding.getACall().getNode() = call } /** Holds if `call` is a call to `overriding`, which overrides `func`. */ -predicate overridden_call(FunctionValue func, FunctionValue overriding, Call call) { +predicate overridden_call(FunctionValue func, FunctionValue overriding, Call call) { overriding.overrides(func) and overriding.getACall().getNode() = call } - diff --git a/python/ql/src/Expressions/CallToSuperWrongClass.ql b/python/ql/src/Expressions/CallToSuperWrongClass.ql index 57ae36fa30e..4f218ab5a2c 100644 --- a/python/ql/src/Expressions/CallToSuperWrongClass.ql +++ b/python/ql/src/Expressions/CallToSuperWrongClass.ql @@ -16,14 +16,14 @@ import python from CallNode call_to_super, string name where -exists(GlobalVariable gv, ControlFlowNode cn | - call_to_super = ClassValue::super_().getACall() and - gv.getId() = "super" and - cn = call_to_super.getArg(0) and - name = call_to_super.getScope().getScope().(Class).getName() and - exists(ClassValue other | - cn.pointsTo(other) and - not other.getScope().getName() = name + exists(GlobalVariable gv, ControlFlowNode cn | + call_to_super = ClassValue::super_().getACall() and + gv.getId() = "super" and + cn = call_to_super.getArg(0) and + name = call_to_super.getScope().getScope().(Class).getName() and + exists(ClassValue other | + cn.pointsTo(other) and + not other.getScope().getName() = name + ) ) -) select call_to_super.getNode(), "First argument to super() should be " + name + "." diff --git a/python/ql/src/Expressions/CompareConstants.ql b/python/ql/src/Expressions/CompareConstants.ql index 2a66a952c5e..5b04302db31 100644 --- a/python/ql/src/Expressions/CompareConstants.ql +++ b/python/ql/src/Expressions/CompareConstants.ql @@ -16,6 +16,8 @@ import python from Compare comparison, Expr left, Expr right where - comparison.compares(left, _, right) and left.isConstant() and right.isConstant() and + comparison.compares(left, _, right) and + left.isConstant() and + right.isConstant() and not exists(Assert a | a.getTest() = comparison) select comparison, "Comparison of constants; use 'True' or 'False' instead." diff --git a/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql b/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql index 9d618c2dbb1..554d7a087b6 100644 --- a/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql +++ b/python/ql/src/Expressions/CompareIdenticalValuesMissingSelf.ql @@ -16,6 +16,5 @@ import python import Expressions.RedundantComparison from RedundantComparison comparison -where - comparison.maybeMissingSelf() +where comparison.maybeMissingSelf() select comparison, "Comparison of identical values; may be missing 'self'." diff --git a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql index 1a1083884ea..29f21e7beb2 100644 --- a/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql +++ b/python/ql/src/Expressions/Comparisons/UselessComparisonTest.ql @@ -15,16 +15,19 @@ import python import semmle.python.Comparisons -/* Holds if the comparison `comp` is of the complex form `a op b op c` and not of +/* + * Holds if the comparison `comp` is of the complex form `a op b op c` and not of * the simple form `a op b`. */ + private predicate is_complex(Expr comp) { exists(comp.(Compare).getOp(1)) or is_complex(comp.(UnaryExpr).getOperand()) } -/** A test is useless if for every block that it controls there is another test that is at least as +/** + * A test is useless if for every block that it controls there is another test that is at least as * strict and also controls that block. */ private predicate useless_test(Comparison comp, ComparisonControlBlock controls, boolean isTrue) { @@ -34,17 +37,15 @@ private predicate useless_test(Comparison comp, ComparisonControlBlock controls, } private predicate useless_test_ast(AstNode comp, AstNode previous, boolean isTrue) { - forex(Comparison compnode, ConditionBlock block| + forex(Comparison compnode, ConditionBlock block | compnode.getNode() = comp and block.getLastNode().getNode() = previous - | + | useless_test(compnode, block, isTrue) ) } from Expr test, Expr other, boolean isTrue -where -useless_test_ast(test, other, isTrue) and not useless_test_ast(test.getAChildNode+(), other, _) - - +where + useless_test_ast(test, other, isTrue) and not useless_test_ast(test.getAChildNode+(), other, _) select test, "Test is always " + isTrue + ", because of $@", other, "this condition" diff --git a/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql b/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql index 20678da8dc0..99a1a0e44e1 100644 --- a/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql +++ b/python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.ql @@ -17,13 +17,12 @@ import semmle.python.strings predicate dict_key(Dict d, Expr k, string s) { k = d.getAKey() and ( - s = ((Num)k).getN() + s = k.(Num).getN() or // We use � to mark unrepresentable characters // so two instances of � may represent different strings in the source code not "�" = s.charAt(_) and - exists(StrConst c | - c = k | + exists(StrConst c | c = k | s = "u\"" + c.getText() + "\"" and c.isUnicode() or s = "b\"" + c.getText() + "\"" and not c.isUnicode() @@ -32,13 +31,15 @@ predicate dict_key(Dict d, Expr k, string s) { } from Dict d, Expr k1, Expr k2 -where exists(string s | dict_key(d, k1, s) and dict_key(d, k2, s) and k1 != k2) and -( - exists(BasicBlock b, int i1, int i2 | - k1.getAFlowNode() = b.getNode(i1) and - k2.getAFlowNode() = b.getNode(i2) and - i1 < i2 - ) or - k1.getAFlowNode().getBasicBlock().strictlyDominates(k2.getAFlowNode().getBasicBlock()) -) +where + exists(string s | dict_key(d, k1, s) and dict_key(d, k2, s) and k1 != k2) and + ( + exists(BasicBlock b, int i1, int i2 | + k1.getAFlowNode() = b.getNode(i1) and + k2.getAFlowNode() = b.getNode(i2) and + i1 < i2 + ) + or + k1.getAFlowNode().getBasicBlock().strictlyDominates(k2.getAFlowNode().getBasicBlock()) + ) select k1, "Dictionary key " + repr(k1) + " is subsequently $@.", k2, "overwritten" diff --git a/python/ql/src/Expressions/ExplicitCallToDel.ql b/python/ql/src/Expressions/ExplicitCallToDel.ql index 1cb2782c885..81e8fc97b43 100644 --- a/python/ql/src/Expressions/ExplicitCallToDel.ql +++ b/python/ql/src/Expressions/ExplicitCallToDel.ql @@ -13,23 +13,22 @@ import python class DelCall extends Call { - DelCall() { - ((Attribute)this.getFunc()).getName() = "__del__" - } - - predicate isSuperCall() { - exists(Function f | f = this.getScope() and f.getName() = "__del__" | - // We pass in `self` as the first argument... - f.getArg(0).asName().getVariable() = ((Name)this.getArg(0)).getVariable() or - // ... or the call is of the form `super(Type, self).__del__()`, or the equivalent - // Python 3: `super().__del__()`. - exists(Call superCall | superCall = ((Attribute)this.getFunc()).getObject() | - ((Name)superCall.getFunc()).getId() = "super" - ) - ) - } + DelCall() { this.getFunc().(Attribute).getName() = "__del__" } + + predicate isSuperCall() { + exists(Function f | f = this.getScope() and f.getName() = "__del__" | + // We pass in `self` as the first argument... + f.getArg(0).asName().getVariable() = this.getArg(0).(Name).getVariable() + or + // ... or the call is of the form `super(Type, self).__del__()`, or the equivalent + // Python 3: `super().__del__()`. + exists(Call superCall | superCall = this.getFunc().(Attribute).getObject() | + superCall.getFunc().(Name).getId() = "super" + ) + ) + } } from DelCall del where not del.isSuperCall() -select del, "The __del__ special method is called explicitly." \ No newline at end of file +select del, "The __del__ special method is called explicitly." diff --git a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll index f32b338c8ac..85b2fbad22a 100644 --- a/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll +++ b/python/ql/src/Expressions/Formatting/AdvancedFormatting.qll @@ -1,11 +1,7 @@ import python - library class PossibleAdvancedFormatString extends StrConst { - - PossibleAdvancedFormatString() { - this.getText().matches("%{%}%") - } + PossibleAdvancedFormatString() { this.getText().matches("%{%}%") } private predicate field(int start, int end) { brace_pair(this, start, end) and @@ -31,83 +27,77 @@ library class PossibleAdvancedFormatString extends StrConst { ( result = this.getText().substring(start, end).regexpCapture("\\{([^!:.\\[]+)[!:.\\[].*", 1) or - result = this.getText().substring(start+1, end-1) and result.regexpMatch("[^!:.\\[]+") + result = this.getText().substring(start + 1, end - 1) and result.regexpMatch("[^!:.\\[]+") ) } /** Gets the name of the formatting field at [start, end) */ string getFieldName(int start, int end) { - result = this.fieldId(start, end) - and not exists(this.getFieldNumber(start, end)) + result = this.fieldId(start, end) and + not exists(this.getFieldNumber(start, end)) } private predicate implicitlyNumberedField(int start, int end) { this.field(start, end) and - exists(string c | - start+1 = this.getText().indexOf(c) | + exists(string c | start + 1 = this.getText().indexOf(c) | c = "}" or c = ":" or c = "!" or c = "." ) } /** Whether this format string has implicitly numbered fields */ - predicate isImplicitlyNumbered() { - this.implicitlyNumberedField(_, _) - } + predicate isImplicitlyNumbered() { this.implicitlyNumberedField(_, _) } /** Whether this format string has explicitly numbered fields */ - predicate isExplicitlyNumbered() { - exists(this.fieldId(_, _).toInt()) - } - + predicate isExplicitlyNumbered() { exists(this.fieldId(_, _).toInt()) } } predicate brace_sequence(PossibleAdvancedFormatString fmt, int index, int len) { - exists(string text | - text = fmt.getText() | - text.charAt(index) = "{" and not text.charAt(index-1) = "{" and len = 1 + exists(string text | text = fmt.getText() | + text.charAt(index) = "{" and not text.charAt(index - 1) = "{" and len = 1 or - text.charAt(index) = "{" and text.charAt(index-1) = "{" and brace_sequence(fmt, index-1, len-1) + text.charAt(index) = "{" and + text.charAt(index - 1) = "{" and + brace_sequence(fmt, index - 1, len - 1) ) } predicate escaped_brace(PossibleAdvancedFormatString fmt, int index) { - exists(int len | - brace_sequence(fmt, index, len) | - len % 2 = 0 - ) + exists(int len | brace_sequence(fmt, index, len) | len % 2 = 0) } predicate escaping_brace(PossibleAdvancedFormatString fmt, int index) { - escaped_brace(fmt, index+1) + escaped_brace(fmt, index + 1) } private predicate inner_brace_pair(PossibleAdvancedFormatString fmt, int start, int end) { not escaping_brace(fmt, start) and not escaped_brace(fmt, start) and fmt.getText().charAt(start) = "{" and - exists(string pair | pair = fmt.getText().suffix(start).regexpCapture("(?s)(\\{([^{}]|\\{\\{)*+\\}).*", 1) | + exists(string pair | + pair = fmt.getText().suffix(start).regexpCapture("(?s)(\\{([^{}]|\\{\\{)*+\\}).*", 1) + | end = start + pair.length() ) } private predicate brace_pair(PossibleAdvancedFormatString fmt, int start, int end) { - inner_brace_pair(fmt, start, end) - or - not escaping_brace(fmt, start) and - not escaped_brace(fmt, start) and - exists(string prefix, string postfix, int innerstart, int innerend | - brace_pair(fmt, innerstart, innerend) and - prefix = fmt.getText().regexpFind("\\{([^{}]|\\{\\{)+\\{", _, start) and - innerstart = start+prefix.length()-1 and - postfix = fmt.getText().regexpFind("\\}([^{}]|\\}\\})*\\}", _, innerend-1) and - end = innerend + postfix.length()-1 - ) + inner_brace_pair(fmt, start, end) + or + not escaping_brace(fmt, start) and + not escaped_brace(fmt, start) and + exists(string prefix, string postfix, int innerstart, int innerend | + brace_pair(fmt, innerstart, innerend) and + prefix = fmt.getText().regexpFind("\\{([^{}]|\\{\\{)+\\{", _, start) and + innerstart = start + prefix.length() - 1 and + postfix = fmt.getText().regexpFind("\\}([^{}]|\\}\\})*\\}", _, innerend - 1) and + end = innerend + postfix.length() - 1 + ) } private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatString fmt, int args) { - exists(CallNode call | - call = format_expr.getAFlowNode() | - call.getFunction().pointsTo(Value::named("format")) and call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and + exists(CallNode call | call = format_expr.getAFlowNode() | + call.getFunction().pointsTo(Value::named("format")) and + call.getArg(0).pointsTo(_, fmt.getAFlowNode()) and args = count(format_expr.getAnArg()) - 1 or call.getFunction().(AttrNode).getObject("format").pointsTo(_, fmt.getAFlowNode()) and @@ -116,26 +106,14 @@ private predicate advanced_format_call(Call format_expr, PossibleAdvancedFormatS } class AdvancedFormatString extends PossibleAdvancedFormatString { - - AdvancedFormatString() { - advanced_format_call(_, this, _) - } - + AdvancedFormatString() { advanced_format_call(_, this, _) } } class AdvancedFormattingCall extends Call { - - AdvancedFormattingCall() { - advanced_format_call(this, _, _) - } + AdvancedFormattingCall() { advanced_format_call(this, _, _) } /** Count of the arguments actually provided */ - int providedArgCount() { - advanced_format_call(this, _, result) - } - - AdvancedFormatString getAFormat() { - advanced_format_call(this, result, _) - } + int providedArgCount() { advanced_format_call(this, _, result) } + AdvancedFormatString getAFormat() { advanced_format_call(this, result, _) } } diff --git a/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql b/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql index 3f488aa9507..a52fada69b0 100644 --- a/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/MixedExplicitImplicitIn3101Format.ql @@ -15,4 +15,4 @@ import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt where call.getAFormat() = fmt and fmt.isImplicitlyNumbered() and fmt.isExplicitlyNumbered() -select fmt, "Formatting string mixes implicitly and explicitly numbered fields." \ No newline at end of file +select fmt, "Formatting string mixes implicitly and explicitly numbered fields." diff --git a/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql b/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql index 67c95277375..89af180099d 100644 --- a/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/UnusedArgumentIn3101Format.ql @@ -11,16 +11,18 @@ */ import python - - import python import AdvancedFormatting int field_count(AdvancedFormatString fmt) { result = max(fmt.getFieldNumber(_, _)) + 1 } from AdvancedFormattingCall call, AdvancedFormatString fmt, int arg_count, int max_field -where arg_count = call.providedArgCount() and max_field = field_count(fmt) and -call.getAFormat() = fmt and not exists(call.getStarargs()) and -forall(AdvancedFormatString other | other = call.getAFormat() | field_count(other) < arg_count) -select call, "Too many arguments for string format. Format $@ requires only " + max_field + ", but " + -arg_count.toString() + " are provided.", fmt, "\"" + fmt.getText() + "\"" +where + arg_count = call.providedArgCount() and + max_field = field_count(fmt) and + call.getAFormat() = fmt and + not exists(call.getStarargs()) and + forall(AdvancedFormatString other | other = call.getAFormat() | field_count(other) < arg_count) +select call, + "Too many arguments for string format. Format $@ requires only " + max_field + ", but " + + arg_count.toString() + " are provided.", fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql b/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql index c902b992b1c..62c598a397e 100644 --- a/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql +++ b/python/ql/src/Expressions/Formatting/UnusedNamedArgumentIn3101Format.ql @@ -14,14 +14,18 @@ import python import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt, string name, string fmt_repr -where call.getAFormat() = fmt and -name = call.getAKeyword().getArg() and -forall(AdvancedFormatString format | format = call.getAFormat() | not format.getFieldName(_, _) = name) -and not exists(call.getKwargs()) and -(strictcount(call.getAFormat()) = 1 and fmt_repr = "format \"" + fmt.getText() + "\"" - or - strictcount(call.getAFormat()) != 1 and fmt_repr = "any format used." -) - -select call, "Surplus named argument for string format. An argument named '" + name + - "' is provided, but it is not required by $@.", fmt, fmt_repr +where + call.getAFormat() = fmt and + name = call.getAKeyword().getArg() and + forall(AdvancedFormatString format | format = call.getAFormat() | + not format.getFieldName(_, _) = name + ) and + not exists(call.getKwargs()) and + ( + strictcount(call.getAFormat()) = 1 and fmt_repr = "format \"" + fmt.getText() + "\"" + or + strictcount(call.getAFormat()) != 1 and fmt_repr = "any format used." + ) +select call, + "Surplus named argument for string format. An argument named '" + name + + "' is provided, but it is not required by $@.", fmt, fmt_repr diff --git a/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql b/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql index 412d8d55830..384d9b9d58e 100644 --- a/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql +++ b/python/ql/src/Expressions/Formatting/WrongNameInArgumentsFor3101Format.ql @@ -15,9 +15,11 @@ import python import AdvancedFormatting from AdvancedFormattingCall call, AdvancedFormatString fmt, string name -where call.getAFormat() = fmt and -not name = call.getAKeyword().getArg() and -fmt.getFieldName(_, _) = name -and not exists(call.getKwargs()) -select call, "Missing named argument for string format. Format $@ requires '" + name + "', but it is omitted.", -fmt, "\"" + fmt.getText() + "\"" \ No newline at end of file +where + call.getAFormat() = fmt and + not name = call.getAKeyword().getArg() and + fmt.getFieldName(_, _) = name and + not exists(call.getKwargs()) +select call, + "Missing named argument for string format. Format $@ requires '" + name + "', but it is omitted.", + fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql b/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql index fe766ae2d8b..8f3479c5be5 100644 --- a/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql +++ b/python/ql/src/Expressions/Formatting/WrongNumberArgumentsFor3101Format.ql @@ -14,10 +14,16 @@ import python import AdvancedFormatting -from AdvancedFormattingCall call, AdvancedFormatString fmt, -int arg_count, int max_field, string provided -where arg_count = call.providedArgCount() and max_field = max(fmt.getFieldNumber(_, _)) and -call.getAFormat() = fmt and not exists(call.getStarargs()) and arg_count <= max_field and -(if arg_count = 1 then provided = " is provided." else provided = " are provided.") -select call, "Too few arguments for string format. Format $@ requires at least " + (max_field+1) + ", but " + -arg_count.toString() + provided, fmt, "\"" + fmt.getText() + "\"" \ No newline at end of file +from + AdvancedFormattingCall call, AdvancedFormatString fmt, int arg_count, int max_field, + string provided +where + arg_count = call.providedArgCount() and + max_field = max(fmt.getFieldNumber(_, _)) and + call.getAFormat() = fmt and + not exists(call.getStarargs()) and + arg_count <= max_field and + (if arg_count = 1 then provided = " is provided." else provided = " are provided.") +select call, + "Too few arguments for string format. Format $@ requires at least " + (max_field + 1) + ", but " + + arg_count.toString() + provided, fmt, "\"" + fmt.getText() + "\"" diff --git a/python/ql/src/Expressions/HashedButNoHash.ql b/python/ql/src/Expressions/HashedButNoHash.ql index 37da9407b7f..7fbb723fc54 100644 --- a/python/ql/src/Expressions/HashedButNoHash.ql +++ b/python/ql/src/Expressions/HashedButNoHash.ql @@ -12,7 +12,8 @@ import python -/* This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing. +/* + * This assumes that any indexing operation where the value is not a sequence or numpy array involves hashing. * For sequences, the index must be an int, which are hashable, so we don't need to treat them specially. * For numpy arrays, the index may be a list, which are not hashable and needs to be treated specially. */ @@ -30,7 +31,9 @@ predicate has_custom_getitem(Value v) { } predicate explicitly_hashed(ControlFlowNode f) { - exists(CallNode c, GlobalVariable hash | c.getArg(0) = f and c.getFunction().(NameNode).uses(hash) and hash.getId() = "hash") + exists(CallNode c, GlobalVariable hash | + c.getArg(0) = f and c.getFunction().(NameNode).uses(hash) and hash.getId() = "hash" + ) } predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode origin) { @@ -44,9 +47,7 @@ predicate unhashable_subscript(ControlFlowNode f, ClassValue c, ControlFlowNode } predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origin) { - exists(Value v | - f.pointsTo(v, origin) and v.getClass() = cls - | + exists(Value v | f.pointsTo(v, origin) and v.getClass() = cls | not cls.hasAttribute("__hash__") and not cls.failedInference(_) and cls.isNewStyle() or cls.lookup("__hash__") = Value::named("None") @@ -67,16 +68,18 @@ predicate is_unhashable(ControlFlowNode f, ClassValue cls, ControlFlowNode origi * it. */ predicate typeerror_is_caught(ControlFlowNode f) { - exists (Try try | + exists(Try try | try.getBody().contains(f.getNode()) and - try.getAHandler().getType().pointsTo(ClassValue::typeError())) + try.getAHandler().getType().pointsTo(ClassValue::typeError()) + ) } from ControlFlowNode f, ClassValue c, ControlFlowNode origin where -not typeerror_is_caught(f) -and -(explicitly_hashed(f) and is_unhashable(f, c, origin) - or - unhashable_subscript(f, c, origin)) + not typeerror_is_caught(f) and + ( + explicitly_hashed(f) and is_unhashable(f, c, origin) + or + unhashable_subscript(f, c, origin) + ) select f.getNode(), "This $@ of $@ is unhashable.", origin, "instance", c, c.getQualifiedName() diff --git a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql index 2a2025ec51e..5dda5b857f9 100644 --- a/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql +++ b/python/ql/src/Expressions/IncorrectComparisonUsingIs.ql @@ -14,7 +14,14 @@ import python import IsComparisons from Compare comp, Cmpop op, ClassValue c, string alt -where invalid_portable_is_comparison(comp, op, c) and -not cpython_interned_constant(comp.getASubExpression()) and -(op instanceof Is and alt = "==" or op instanceof IsNot and alt = "!=") -select comp, "Values compared using '" + op.getSymbol() + "' when equivalence is not the same as identity. Use '" + alt + "' instead." +where + invalid_portable_is_comparison(comp, op, c) and + not cpython_interned_constant(comp.getASubExpression()) and + ( + op instanceof Is and alt = "==" + or + op instanceof IsNot and alt = "!=" + ) +select comp, + "Values compared using '" + op.getSymbol() + + "' when equivalence is not the same as identity. Use '" + alt + "' instead." diff --git a/python/ql/src/Expressions/IsComparisons.qll b/python/ql/src/Expressions/IsComparisons.qll index bf9d8bb71db..8b0fc79a2b1 100644 --- a/python/ql/src/Expressions/IsComparisons.qll +++ b/python/ql/src/Expressions/IsComparisons.qll @@ -1,9 +1,9 @@ import python - predicate comparison_using_is(Compare comp, ControlFlowNode left, Cmpop op, ControlFlowNode right) { exists(CompareNode fcomp | fcomp = comp.getAFlowNode() | - fcomp.operands(left, op, right) and (op instanceof Is or op instanceof IsNot) + fcomp.operands(left, op, right) and + (op instanceof Is or op instanceof IsNot) ) } @@ -12,8 +12,7 @@ predicate overrides_eq_or_cmp(ClassValue c) { or c.declaresAttribute("__eq__") and not c = Value::named("object") or - exists(ClassValue sup | - sup = c.getASuperType() and not sup = Value::named("object") | + exists(ClassValue sup | sup = c.getASuperType() and not sup = Value::named("object") | sup.declaresAttribute("__eq__") ) or @@ -29,58 +28,56 @@ predicate probablySingleton(ClassValue cls) { predicate invalid_to_use_is_portably(ClassValue c) { overrides_eq_or_cmp(c) and // Exclude type/builtin-function/bool as it is legitimate to compare them using 'is' but they implement __eq__ - not c = Value::named("type") and not c = ClassValue::builtinFunction() and not c = Value::named("bool") and + not c = Value::named("type") and + not c = ClassValue::builtinFunction() and + not c = Value::named("bool") and // OK to compare with 'is' if a singleton not probablySingleton(c) } predicate simple_constant(ControlFlowNode f) { - exists(Value val | f.pointsTo(val) | val = Value::named("True") or val = Value::named("False") or val = Value::named("None")) + exists(Value val | f.pointsTo(val) | + val = Value::named("True") or val = Value::named("False") or val = Value::named("None") + ) } private predicate cpython_interned_value(Expr e) { exists(string text | text = e.(StrConst).getText() | - text.length() = 0 or + text.length() = 0 + or text.length() = 1 and text.regexpMatch("[U+0000-U+00ff]") - ) - or - exists(int i | - i = e.(IntegerLiteral).getN().toInt() | - -5 <= i and i <= 256 ) or + exists(int i | i = e.(IntegerLiteral).getN().toInt() | -5 <= i and i <= 256) + or exists(Tuple t | t = e and not exists(t.getAnElt())) } -/** The set of values that can be expected to be interned across +/** + * The set of values that can be expected to be interned across * the main implementations of Python. PyPy, Jython, etc tend to * follow CPython, but it varies, so this is a best guess. */ private predicate universally_interned_value(Expr e) { - e.(IntegerLiteral).getN().toInt() = 0 - or - exists(Tuple t | t = e and not exists(t.getAnElt())) - or - e.(StrConst).getText() = "" + e.(IntegerLiteral).getN().toInt() = 0 + or + exists(Tuple t | t = e and not exists(t.getAnElt())) + or + e.(StrConst).getText() = "" } predicate cpython_interned_constant(Expr e) { - exists(Expr const | - e.pointsTo(_, const) | - cpython_interned_value(const) - ) + exists(Expr const | e.pointsTo(_, const) | cpython_interned_value(const)) } predicate universally_interned_constant(Expr e) { - exists(Expr const | - e.pointsTo(_, const) | - universally_interned_value(const) - ) + exists(Expr const | e.pointsTo(_, const) | universally_interned_value(const)) } private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, ClassValue cls2) { exists(ControlFlowNode op1, ControlFlowNode op2 | - comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1) | + comparison_using_is(comp, op1, op, op2) or comparison_using_is(comp, op2, op, op1) + | op1.inferredValue().getClass() = cls1 and op2.inferredValue().getClass() = cls2 ) @@ -89,15 +86,17 @@ private predicate comparison_both_types(Compare comp, Cmpop op, ClassValue cls1, private predicate comparison_one_type(Compare comp, Cmpop op, ClassValue cls) { not comparison_both_types(comp, _, _, _) and exists(ControlFlowNode operand | - comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand) | - operand.inferredValue().getClass() = cls + comparison_using_is(comp, operand, op, _) or comparison_using_is(comp, _, op, operand) + | + operand.inferredValue().getClass() = cls ) } predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) { // OK to use 'is' when defining '__eq__' - not exists(Function eq | eq.getName() = "__eq__" or eq.getName() = "__ne__" | eq = comp.getScope().getScope*()) - and + not exists(Function eq | eq.getName() = "__eq__" or eq.getName() = "__ne__" | + eq = comp.getScope().getScope*() + ) and ( comparison_one_type(comp, op, cls) and invalid_to_use_is_portably(cls) or @@ -105,32 +104,32 @@ predicate invalid_portable_is_comparison(Compare comp, Cmpop op, ClassValue cls) invalid_to_use_is_portably(cls) and invalid_to_use_is_portably(other) ) - ) - and + ) and // OK to use 'is' when comparing items from a known set of objects not exists(Expr left, Expr right, Value val | comp.compares(left, op, right) and - exists(ImmutableLiteral il | il.getLiteralValue() = val) | + exists(ImmutableLiteral il | il.getLiteralValue() = val) + | left.pointsTo(val) and right.pointsTo(val) or // Simple constant in module, probably some sort of sentinel exists(AstNode origin | - not left.pointsTo(_) and right.pointsTo(val, origin) and + not left.pointsTo(_) and + right.pointsTo(val, origin) and origin.getScope().getEnclosingModule() = comp.getScope().getEnclosingModule() ) - ) - and + ) and // OK to use 'is' when comparing with a member of an enum not exists(Expr left, Expr right, AstNode origin | comp.compares(left, op, right) and - enum_member(origin) | + enum_member(origin) + | left.pointsTo(_, origin) or right.pointsTo(_, origin) ) } private predicate enum_member(AstNode obj) { - exists(ClassValue cls, AssignStmt asgn | - cls.getASuperType().getName() = "Enum" | + exists(ClassValue cls, AssignStmt asgn | cls.getASuperType().getName() = "Enum" | cls.getScope() = asgn.getScope() and asgn.getValue() = obj ) diff --git a/python/ql/src/Expressions/NonCallableCalled.ql b/python/ql/src/Expressions/NonCallableCalled.ql index 2f9a0f8f5cc..fdd0bbd13c3 100644 --- a/python/ql/src/Expressions/NonCallableCalled.ql +++ b/python/ql/src/Expressions/NonCallableCalled.ql @@ -15,10 +15,13 @@ import python import Exceptions.NotImplemented from Call c, Value v, ClassValue t, Expr f, AstNode origin -where f = c.getFunc() and f.pointsTo(v, origin) and t = v.getClass() and - not t.isCallable() and not t.failedInference(_) - and not t.hasAttribute("__get__") - and not v = Value::named("None") - and not use_of_not_implemented_in_raise(_, f) - +where + f = c.getFunc() and + f.pointsTo(v, origin) and + t = v.getClass() and + not t.isCallable() and + not t.failedInference(_) and + not t.hasAttribute("__get__") and + not v = Value::named("None") and + not use_of_not_implemented_in_raise(_, f) select c, "Call to a $@ of $@.", origin, "non-callable", t, t.toString() diff --git a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql index d5aefebd3ce..3e01ccdacf7 100644 --- a/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql +++ b/python/ql/src/Expressions/NonPortableComparisonUsingIs.ql @@ -14,10 +14,12 @@ import python import IsComparisons from Compare comp, Cmpop op, ClassValue c -where invalid_portable_is_comparison(comp, op, c) and -exists(Expr sub | - sub = comp.getASubExpression() | - cpython_interned_constant(sub) and - not universally_interned_constant(sub) -) -select comp, "The result of this comparison with '" + op.getSymbol() + "' may differ between implementations of Python." \ No newline at end of file +where + invalid_portable_is_comparison(comp, op, c) and + exists(Expr sub | sub = comp.getASubExpression() | + cpython_interned_constant(sub) and + not universally_interned_constant(sub) + ) +select comp, + "The result of this comparison with '" + op.getSymbol() + + "' may differ between implementations of Python." diff --git a/python/ql/src/Expressions/RedundantComparison.qll b/python/ql/src/Expressions/RedundantComparison.qll index 64f80ce31b5..7c2d9857849 100644 --- a/python/ql/src/Expressions/RedundantComparison.qll +++ b/python/ql/src/Expressions/RedundantComparison.qll @@ -1,27 +1,22 @@ import python class RedundantComparison extends Compare { - RedundantComparison() { exists(Expr left, Expr right | - this.compares(left, _, right) - and + this.compares(left, _, right) and same_variable(left, right) ) } - + predicate maybeMissingSelf() { exists(Name left | this.compares(left, _, _) and not this.isConstant() and exists(Class cls | left.getScope().getScope() = cls | - exists(SelfAttribute sa | sa.getName() = left.getId() | - sa.getClass() = cls - ) + exists(SelfAttribute sa | sa.getName() = left.getId() | sa.getClass() = cls) ) ) } - } private predicate same_variable(Expr left, Expr right) { @@ -36,11 +31,14 @@ private predicate name_in_comparison(Compare comp, Name n, Variable v) { private predicate same_name(Name n1, Name n2) { n1 != n2 and - exists(Compare comp, Variable v | name_in_comparison(comp, n1, v) and name_in_comparison(comp, n2, v)) + exists(Compare comp, Variable v | + name_in_comparison(comp, n1, v) and name_in_comparison(comp, n2, v) + ) } private predicate same_attribute(Attribute a1, Attribute a2) { a1 != a2 and exists(Compare comp | comp.contains(a1) and comp.contains(a2)) and - a1.getName() = a2.getName() and same_name(a1.getObject(), a2.getObject()) + a1.getName() = a2.getName() and + same_name(a1.getObject(), a2.getObject()) } diff --git a/python/ql/src/Expressions/Regex/BackspaceEscape.ql b/python/ql/src/Expressions/Regex/BackspaceEscape.ql index b80893b04f0..b18d581257a 100644 --- a/python/ql/src/Expressions/Regex/BackspaceEscape.ql +++ b/python/ql/src/Expressions/Regex/BackspaceEscape.ql @@ -14,9 +14,8 @@ import python import semmle.python.regex from Regex r, int offset -where r.escapingChar(offset) and r.getChar(offset+1) = "b" and -exists(int start, int end | - start < offset and end > offset | - r.charSet(start, end) -) -select r, "Backspace escape in regular expression at offset " + offset + "." \ No newline at end of file +where + r.escapingChar(offset) and + r.getChar(offset + 1) = "b" and + exists(int start, int end | start < offset and end > offset | r.charSet(start, end)) +select r, "Backspace escape in regular expression at offset " + offset + "." diff --git a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql index 88c265fb370..42a745affb8 100644 --- a/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql +++ b/python/ql/src/Expressions/Regex/DuplicateCharacterInSet.ql @@ -15,20 +15,28 @@ import semmle.python.regex predicate duplicate_char_in_class(Regex r, string char) { exists(int i, int j, int x, int y, int start, int end | - i != x and j != y and - start < i and j < end and - start < x and y < end and - r.character(i, j) and char = r.getText().substring(i, j) and - r.character(x, y) and char = r.getText().substring(x, y) and + i != x and + j != y and + start < i and + j < end and + start < x and + y < end and + r.character(i, j) and + char = r.getText().substring(i, j) and + r.character(x, y) and + char = r.getText().substring(x, y) and r.charSet(start, end) ) and /* Exclude � as we use it for any unencodable character */ char != "�" and //Ignore whitespace in verbose mode - not (r.getAMode() = "VERBOSE" and (char = " " or char = "\t" or char = "\r" or char = "\n")) + not ( + r.getAMode() = "VERBOSE" and + (char = " " or char = "\t" or char = "\r" or char = "\n") + ) } from Regex r, string char where duplicate_char_in_class(r, char) -select r, "This regular expression includes duplicate character '" + char + "' in a set of characters." - +select r, + "This regular expression includes duplicate character '" + char + "' in a set of characters." diff --git a/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql b/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql index 7a1974fc514..ea5deffa7de 100644 --- a/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql +++ b/python/ql/src/Expressions/Regex/MissingPartSpecialGroup.ql @@ -16,5 +16,3 @@ import semmle.python.regex from Regex r, string missing, string part where r.getText().regexpMatch(".*\\(P<\\w+>.*") and missing = "?" and part = "named group" select r, "Regular expression is missing '" + missing + "' in " + part + "." - - diff --git a/python/ql/src/Expressions/Regex/UnmatchableCaret.ql b/python/ql/src/Expressions/Regex/UnmatchableCaret.ql index 7fc0c6f219e..7a5c087ec02 100644 --- a/python/ql/src/Expressions/Regex/UnmatchableCaret.ql +++ b/python/ql/src/Expressions/Regex/UnmatchableCaret.ql @@ -16,10 +16,11 @@ import semmle.python.regex predicate unmatchable_caret(Regex r, int start) { not r.getAMode() = "MULTILINE" and not r.getAMode() = "VERBOSE" and - r.specialCharacter(start, start+1, "^") and - not r.firstItem(start, start+1) + r.specialCharacter(start, start + 1, "^") and + not r.firstItem(start, start + 1) } from Regex r, int offset where unmatchable_caret(r, offset) -select r, "This regular expression includes an unmatchable caret at offset " + offset.toString() + "." +select r, + "This regular expression includes an unmatchable caret at offset " + offset.toString() + "." diff --git a/python/ql/src/Expressions/Regex/UnmatchableDollar.ql b/python/ql/src/Expressions/Regex/UnmatchableDollar.ql index 49cef2bded1..dfd2bfcf893 100644 --- a/python/ql/src/Expressions/Regex/UnmatchableDollar.ql +++ b/python/ql/src/Expressions/Regex/UnmatchableDollar.ql @@ -16,11 +16,11 @@ import semmle.python.regex predicate unmatchable_dollar(Regex r, int start) { not r.getAMode() = "MULTILINE" and not r.getAMode() = "VERBOSE" and - r.specialCharacter(start, start+1, "$") - and - not r.lastItem(start, start+1) + r.specialCharacter(start, start + 1, "$") and + not r.lastItem(start, start + 1) } from Regex r, int offset where unmatchable_dollar(r, offset) -select r, "This regular expression includes an unmatchable dollar at offset " + offset.toString() + "." +select r, + "This regular expression includes an unmatchable dollar at offset " + offset.toString() + "." diff --git a/python/ql/src/Expressions/TruncatedDivision.ql b/python/ql/src/Expressions/TruncatedDivision.ql index 471b5244de0..399435dbabf 100644 --- a/python/ql/src/Expressions/TruncatedDivision.ql +++ b/python/ql/src/Expressions/TruncatedDivision.ql @@ -1,38 +1,37 @@ - /** - * @name Result of integer division may be truncated - * @description The arguments to a division statement may be integers, which - * may cause the result to be truncated in Python 2. - * @kind problem - * @tags maintainability - * correctness - * @problem.severity warning - * @sub-severity high - * @precision very-high - * @id py/truncated-division - */ +/** + * @name Result of integer division may be truncated + * @description The arguments to a division statement may be integers, which + * may cause the result to be truncated in Python 2. + * @kind problem + * @tags maintainability + * correctness + * @problem.severity warning + * @sub-severity high + * @precision very-high + * @id py/truncated-division + */ import python from BinaryExpr div, ControlFlowNode left, ControlFlowNode right where // Only relevant for Python 2, as all later versions implement true division - major_version() = 2 - and + major_version() = 2 and exists(BinaryExprNode bin, Value lval, Value rval | - bin = div.getAFlowNode() - and bin.getNode().getOp() instanceof Div - and bin.getLeft().pointsTo(lval, left) - and lval.getClass() = ClassValue::int_() - and bin.getRight().pointsTo(rval, right) - and rval.getClass() = ClassValue::int_() + bin = div.getAFlowNode() and + bin.getNode().getOp() instanceof Div and + bin.getLeft().pointsTo(lval, left) and + lval.getClass() = ClassValue::int_() and + bin.getRight().pointsTo(rval, right) and + rval.getClass() = ClassValue::int_() and // Ignore instances where integer division leaves no remainder - and not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 - and not bin.getNode().getEnclosingModule().hasFromFuture("division") + not lval.(NumericValue).getIntValue() % rval.(NumericValue).getIntValue() = 0 and + not bin.getNode().getEnclosingModule().hasFromFuture("division") and // Filter out results wrapped in `int(...)` - and not exists(CallNode c | - c = ClassValue::int_().getACall() - and c.getAnArg() = bin + not exists(CallNode c | + c = ClassValue::int_().getACall() and + c.getAnArg() = bin ) ) select div, "Result of division may be truncated as its $@ and $@ arguments may both be integers.", - left.getLocation(), "left", right.getLocation(), "right" + left.getLocation(), "left", right.getLocation(), "right" diff --git a/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql b/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql index 70128406915..8199be8a051 100644 --- a/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql +++ b/python/ql/src/Expressions/UnintentionalImplicitStringConcatenation.ql @@ -22,14 +22,13 @@ predicate string_const(Expr s) { from StrConst s where -// Implicitly concatenated string is in a list and that list contains at least one other string. -exists(List l, Expr other | - not s = other and - l.getAnElt() = s and - l.getAnElt() = other and - string_const(other) -) and -exists(s.getAnImplicitlyConcatenatedPart()) and -not s.isParenthesized() - + // Implicitly concatenated string is in a list and that list contains at least one other string. + exists(List l, Expr other | + not s = other and + l.getAnElt() = s and + l.getAnElt() = other and + string_const(other) + ) and + exists(s.getAnImplicitlyConcatenatedPart()) and + not s.isParenthesized() select s, "Implicit string concatenation. Maybe missing a comma?" diff --git a/python/ql/src/Expressions/UnnecessaryLambda.ql b/python/ql/src/Expressions/UnnecessaryLambda.ql index 2d7bbf72682..2b927973015 100644 --- a/python/ql/src/Expressions/UnnecessaryLambda.ql +++ b/python/ql/src/Expressions/UnnecessaryLambda.ql @@ -15,43 +15,47 @@ import python /* f consists of a single return statement, whose value is a call. The arguments of the call are exactly the parameters of f */ predicate simple_wrapper(Lambda l, Expr wrapped) { exists(Function f, Call c | f = l.getInnerScope() and c = l.getExpression() | - wrapped = c.getFunc() and - count(f.getAnArg()) = count(c.getAnArg()) and - forall(int arg | exists(f.getArg(arg)) | - f.getArgName(arg) = ((Name)c.getArg(arg)).getId()) and - /* Either no **kwargs or they must match */ - (not exists(f.getKwarg()) and not exists(c.getKwargs()) or - ((Name)f.getKwarg()).getId() = ((Name)c.getKwargs()).getId()) and - /* Either no *args or they must match */ - (not exists(f.getVararg()) and not exists(c.getStarargs()) or - ((Name)f.getVararg()).getId() = ((Name)c.getStarargs()).getId()) and - /* No named parameters in call */ - not exists(c.getAKeyword()) - ) - and + wrapped = c.getFunc() and + count(f.getAnArg()) = count(c.getAnArg()) and + forall(int arg | exists(f.getArg(arg)) | f.getArgName(arg) = c.getArg(arg).(Name).getId()) and + /* Either no **kwargs or they must match */ + ( + not exists(f.getKwarg()) and not exists(c.getKwargs()) + or + f.getKwarg().(Name).getId() = c.getKwargs().(Name).getId() + ) and + /* Either no *args or they must match */ + ( + not exists(f.getVararg()) and not exists(c.getStarargs()) + or + f.getVararg().(Name).getId() = c.getStarargs().(Name).getId() + ) and + /* No named parameters in call */ + not exists(c.getAKeyword()) + ) and // f is not necessarily a drop-in replacement for the lambda if there are default argument values not exists(l.getArgs().getADefault()) } /* The expression called will refer to the same object if evaluated when the lambda is created or when the lambda is executed. */ predicate unnecessary_lambda(Lambda l, Expr e) { - simple_wrapper(l, e) and + simple_wrapper(l, e) and ( - /* plain class */ - exists(ClassValue c | e.pointsTo(c)) - or - /* plain function */ - exists(FunctionValue f | e.pointsTo(f)) - or - /* bound-method of enclosing instance */ - exists(ClassValue cls, Attribute a | - cls.getScope() = l.getScope().getScope() and a = e | - ((Name)a.getObject()).getId() = "self" and - cls.hasAttribute(a.getName()) - ) + /* plain class */ + exists(ClassValue c | e.pointsTo(c)) + or + /* plain function */ + exists(FunctionValue f | e.pointsTo(f)) + or + /* bound-method of enclosing instance */ + exists(ClassValue cls, Attribute a | cls.getScope() = l.getScope().getScope() and a = e | + a.getObject().(Name).getId() = "self" and + cls.hasAttribute(a.getName()) + ) ) } from Lambda l, Expr e where unnecessary_lambda(l, e) -select l, "This 'lambda' is just a simple wrapper around a callable object. Use that object directly." \ No newline at end of file +select l, + "This 'lambda' is just a simple wrapper around a callable object. Use that object directly." diff --git a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql index 6abab859f5f..4800f898c54 100644 --- a/python/ql/src/Expressions/WrongNameForArgumentInCall.ql +++ b/python/ql/src/Expressions/WrongNameForArgumentInCall.ql @@ -16,11 +16,12 @@ import python import Expressions.CallArgs - from Call call, FunctionObject func, string name where -illegally_named_parameter_objectapi(call, func, name) and -not func.isAbstract() and -not exists(FunctionObject overridden | func.overrides(overridden) and overridden.getFunction().getAnArg().(Name).getId() = name) -select -call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", func, func.descriptiveString() + illegally_named_parameter_objectapi(call, func, name) and + not func.isAbstract() and + not exists(FunctionObject overridden | + func.overrides(overridden) and overridden.getFunction().getAnArg().(Name).getId() = name + ) +select call, "Keyword argument '" + name + "' is not a supported parameter name of $@.", func, + func.descriptiveString() diff --git a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql index 71d5bec2fca..39d265fe290 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsForFormat.ql @@ -18,29 +18,30 @@ import semmle.python.strings predicate string_format(BinaryExpr operation, StrConst str, Value args, AstNode origin) { operation.getOp() instanceof Mod and exists(Value fmt, Context ctx | - operation.getLeft().pointsTo(ctx, fmt, str) and - operation.getRight().pointsTo(ctx, args, origin) + operation.getLeft().pointsTo(ctx, fmt, str) and + operation.getRight().pointsTo(ctx, args, origin) ) } int sequence_length(Value args) { /* Guess length of sequence */ - exists(Tuple seq, AstNode origin | - seq.pointsTo(args,origin) | + exists(Tuple seq, AstNode origin | seq.pointsTo(args, origin) | result = strictcount(seq.getAnElt()) and not seq.getAnElt() instanceof Starred ) or - exists(ImmutableLiteral i | - i.getLiteralValue() = args | - result = 1 - ) + exists(ImmutableLiteral i | i.getLiteralValue() = args | result = 1) } - -from BinaryExpr operation, StrConst fmt, Value args, int slen, int alen, AstNode origin, string provided -where string_format(operation, fmt, args, origin) and slen = sequence_length(args) and alen = format_items(fmt) and slen != alen and -(if slen = 1 then provided = " is provided." else provided = " are provided.") -select operation, "Wrong number of $@ for string format. Format $@ takes " + alen.toString() + ", but " + slen.toString() + provided, - origin, "arguments", - fmt, fmt.getText() +from + BinaryExpr operation, StrConst fmt, Value args, int slen, int alen, AstNode origin, + string provided +where + string_format(operation, fmt, args, origin) and + slen = sequence_length(args) and + alen = format_items(fmt) and + slen != alen and + (if slen = 1 then provided = " is provided." else provided = " are provided.") +select operation, + "Wrong number of $@ for string format. Format $@ takes " + alen.toString() + ", but " + + slen.toString() + provided, origin, "arguments", fmt, fmt.getText() diff --git a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql index 9f636213a34..732cb7a8b7e 100644 --- a/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql +++ b/python/ql/src/Expressions/WrongNumberArgumentsInCall.ql @@ -16,15 +16,20 @@ import CallArgs from Call call, FunctionObject func, string too, string should, int limit where -( - too_many_args_objectapi(call, func, limit) and too = "too many arguments" and should = "no more than " - or - too_few_args_objectapi(call, func, limit) and too = "too few arguments" and should = "no fewer than " -) and -not func.isAbstract() and -not exists(FunctionObject overridden | func.overrides(overridden) and correct_args_if_called_as_method_objectapi(call, overridden)) -/* The semantics of `__new__` can be a bit subtle, so we simply exclude `__new__` methods */ -and not func.getName() = "__new__" - -select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", func, func.descriptiveString() - + ( + too_many_args_objectapi(call, func, limit) and + too = "too many arguments" and + should = "no more than " + or + too_few_args_objectapi(call, func, limit) and + too = "too few arguments" and + should = "no fewer than " + ) and + not func.isAbstract() and + not exists(FunctionObject overridden | + func.overrides(overridden) and correct_args_if_called_as_method_objectapi(call, overridden) + ) and + /* The semantics of `__new__` can be a bit subtle, so we simply exclude `__new__` methods */ + not func.getName() = "__new__" +select call, "Call to $@ with " + too + "; should be " + should + limit.toString() + ".", func, + func.descriptiveString() diff --git a/python/ql/src/Filters/ClassifyFiles.ql b/python/ql/src/Filters/ClassifyFiles.ql index 4448d993903..20062f0451f 100644 --- a/python/ql/src/Filters/ClassifyFiles.ql +++ b/python/ql/src/Filters/ClassifyFiles.ql @@ -11,8 +11,9 @@ import semmle.python.filters.GeneratedCode import semmle.python.filters.Tests predicate classify(File f, string tag) { - f instanceof GeneratedFile and tag = "generated" or - exists (TestScope t | t.getLocation().getFile() = f) and tag = "test" + f instanceof GeneratedFile and tag = "generated" + or + exists(TestScope t | t.getLocation().getFile() = f) and tag = "test" } from File f, string tag diff --git a/python/ql/src/Filters/NotGenerated.ql b/python/ql/src/Filters/NotGenerated.ql index c59368eb9d8..e1efbfd42e3 100644 --- a/python/ql/src/Filters/NotGenerated.ql +++ b/python/ql/src/Filters/NotGenerated.ql @@ -4,6 +4,7 @@ * @kind problem * @id py/not-generated-file-filter */ + import python import external.DefectFilter import semmle.python.filters.GeneratedCode diff --git a/python/ql/src/Filters/NotTest.ql b/python/ql/src/Filters/NotTest.ql index ddea7fd212b..56650e4ff15 100644 --- a/python/ql/src/Filters/NotTest.ql +++ b/python/ql/src/Filters/NotTest.ql @@ -4,6 +4,7 @@ * @kind problem * @id py/not-test-file-filter */ + import python import external.DefectFilter import semmle.python.filters.Tests diff --git a/python/ql/src/Functions/ConsistentReturns.ql b/python/ql/src/Functions/ConsistentReturns.ql index f3344bd8f74..9e28dee36a3 100644 --- a/python/ql/src/Functions/ConsistentReturns.ql +++ b/python/ql/src/Functions/ConsistentReturns.ql @@ -13,20 +13,21 @@ import python predicate explicitly_returns_non_none(Function func) { - exists(Return return | return.getScope() = func and - exists(Expr val | - val= return.getValue() | - not val instanceof None - ) + exists(Return return | + return.getScope() = func and + exists(Expr val | val = return.getValue() | not val instanceof None) ) } predicate has_implicit_return(Function func) { - exists(ControlFlowNode fallthru | fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable()) or + exists(ControlFlowNode fallthru | + fallthru = func.getFallthroughNode() and not fallthru.unlikelyReachable() + ) + or exists(Return return | return.getScope() = func and not exists(return.getValue())) } - from Function func where explicitly_returns_non_none(func) and has_implicit_return(func) -select func, "Mixing implicit and explicit returns may indicate an error as implicit returns always return None." +select func, + "Mixing implicit and explicit returns may indicate an error as implicit returns always return None." diff --git a/python/ql/src/Functions/DeprecatedSliceMethod.ql b/python/ql/src/Functions/DeprecatedSliceMethod.ql index ff2df9919a6..c37f2195b54 100644 --- a/python/ql/src/Functions/DeprecatedSliceMethod.ql +++ b/python/ql/src/Functions/DeprecatedSliceMethod.ql @@ -12,13 +12,13 @@ import python predicate slice_method_name(string name) { - name = "__getslice__" or name = "__setslice__" or name = "__delslice__" + name = "__getslice__" or name = "__setslice__" or name = "__delslice__" } from PythonFunctionValue f, string meth - -where f.getScope().isMethod() and not f.isOverridingMethod() and - slice_method_name(meth) and f.getName() = meth - - -select f, meth + " method has been deprecated since Python 2.0" \ No newline at end of file +where + f.getScope().isMethod() and + not f.isOverridingMethod() and + slice_method_name(meth) and + f.getName() = meth +select f, meth + " method has been deprecated since Python 2.0" diff --git a/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql b/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql index c1e497ac470..c9368173a76 100644 --- a/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql +++ b/python/ql/src/Functions/IncorrectRaiseInSpecialMethod.ql @@ -22,44 +22,87 @@ private predicate indexing_method(string name) { } private predicate arithmetic_method(string name) { - name = "__add__" or name = "__sub__" or name = "__div__" or - name = "__pos__" or name = "__abs__" or name = "__floordiv__" or - name = "__div__" or name = "__divmod__" or name = "__lshift__" or - name = "__and__" or name = "__or__"or name = "__xor__" or name = "__rshift__" or - name = "__pow__" or name = "__mul__" or name = "__neg__" or - name = "__radd__" or name = "__rsub__" or name = "__rdiv__" or - name = "__rfloordiv__" or name = "__rdiv__" or name = "__rlshift__" or - name = "__rand__" or name = "__ror__"or name = "__rxor__" or name = "__rrshift__" or - name = "__rpow__" or name = "__rmul__" or name = "__truediv__" or name = "__rtruediv__" or - name = "__iadd__" or name = "__isub__" or name = "__idiv__" or - name = "__ifloordiv__" or name = "__idiv__" or name = "__ilshift__" or - name = "__iand__" or name = "__ior__"or name = "__ixor__" or name = "__irshift__" or - name = "__ipow__" or name = "__imul__" or name = "__itruediv__" + name = "__add__" or + name = "__sub__" or + name = "__div__" or + name = "__pos__" or + name = "__abs__" or + name = "__floordiv__" or + name = "__div__" or + name = "__divmod__" or + name = "__lshift__" or + name = "__and__" or + name = "__or__" or + name = "__xor__" or + name = "__rshift__" or + name = "__pow__" or + name = "__mul__" or + name = "__neg__" or + name = "__radd__" or + name = "__rsub__" or + name = "__rdiv__" or + name = "__rfloordiv__" or + name = "__rdiv__" or + name = "__rlshift__" or + name = "__rand__" or + name = "__ror__" or + name = "__rxor__" or + name = "__rrshift__" or + name = "__rpow__" or + name = "__rmul__" or + name = "__truediv__" or + name = "__rtruediv__" or + name = "__iadd__" or + name = "__isub__" or + name = "__idiv__" or + name = "__ifloordiv__" or + name = "__idiv__" or + name = "__ilshift__" or + name = "__iand__" or + name = "__ior__" or + name = "__ixor__" or + name = "__irshift__" or + name = "__ipow__" or + name = "__imul__" or + name = "__itruediv__" } private predicate ordering_method(string name) { - name = "__lt__" or name = "__le__" or name = "__gt__" or name = "__ge__" or + name = "__lt__" + or + name = "__le__" + or + name = "__gt__" + or + name = "__ge__" + or name = "__cmp__" and major_version() = 2 } private predicate cast_method(string name) { - name = "__nonzero__" and major_version() = 2 or - name = "__bool__" or - name = "__int__" or name = "__float__" or - name = "__long__" or - name = "__trunc__" or + name = "__nonzero__" and major_version() = 2 + or + name = "__bool__" + or + name = "__int__" + or + name = "__float__" + or + name = "__long__" + or + name = "__trunc__" + or name = "__complex__" } predicate correct_raise(string name, ClassObject ex) { - ex.getAnImproperSuperType() = theTypeErrorType() - and + ex.getAnImproperSuperType() = theTypeErrorType() and ( - name = "__copy__" or - name = "__deepcopy__" or - name = "__call__" or - indexing_method(name) or - attribute_method(name) + name = "__copy__" or + name = "__deepcopy__" or + name = "__call__" or + indexing_method(name) or + attribute_method(name) ) or preferred_raise(name, ex) @@ -84,11 +127,11 @@ predicate no_need_to_raise(string name, string message) { } predicate is_abstract(FunctionObject func) { - ((Name)func.getFunction().getADecorator()).getId().matches("%abstract%") + func.getFunction().getADecorator().(Name).getId().matches("%abstract%") } predicate always_raises(FunctionObject f, ClassObject ex) { - ex = f.getARaisedType() and + ex = f.getARaisedType() and strictcount(f.getARaisedType()) = 1 and not exists(f.getFunction().getANormalExit()) and /* raising StopIteration is equivalent to a return in a generator */ @@ -96,17 +139,17 @@ predicate always_raises(FunctionObject f, ClassObject ex) { } from FunctionObject f, ClassObject cls, string message -where f.getFunction().isSpecialMethod() and -not is_abstract(f) and -always_raises(f, cls) and -( - no_need_to_raise(f.getName(), message) and not cls.getName() = "NotImplementedError" - or - not correct_raise(f.getName(), cls) and not cls.getName() = "NotImplementedError" - and - exists(ClassObject preferred | - preferred_raise(f.getName(), preferred) | - message = "raise " + preferred.getName() + " instead" +where + f.getFunction().isSpecialMethod() and + not is_abstract(f) and + always_raises(f, cls) and + ( + no_need_to_raise(f.getName(), message) and not cls.getName() = "NotImplementedError" + or + not correct_raise(f.getName(), cls) and + not cls.getName() = "NotImplementedError" and + exists(ClassObject preferred | preferred_raise(f.getName(), preferred) | + message = "raise " + preferred.getName() + " instead" + ) ) -) select f, "Function always raises $@; " + message, cls, cls.toString() diff --git a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql index a425079cce0..53d70815ddd 100644 --- a/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlyOverriddenMethod.ql @@ -14,14 +14,18 @@ import Expressions.CallArgs from Call call, FunctionObject func, FunctionObject overridden, string problem where -func.overrides(overridden) and ( - wrong_args_objectapi(call, func, _, problem) and correct_args_if_called_as_method_objectapi(call, overridden) - or - exists(string name | - illegally_named_parameter_objectapi(call, func, name) and problem = "an argument named '" + name + "'" and - overridden.getFunction().getAnArg().(Name).getId() = name + func.overrides(overridden) and + ( + wrong_args_objectapi(call, func, _, problem) and + correct_args_if_called_as_method_objectapi(call, overridden) + or + exists(string name | + illegally_named_parameter_objectapi(call, func, name) and + problem = "an argument named '" + name + "'" and + overridden.getFunction().getAnArg().(Name).getId() = name + ) ) -) - -select func, "Overriding method signature does not match $@, where it is passed " + problem + ". Overridden method $@ is correctly specified.", -call, "here", overridden, overridden.descriptiveString() +select func, + "Overriding method signature does not match $@, where it is passed " + problem + + ". Overridden method $@ is correctly specified.", call, "here", overridden, + overridden.descriptiveString() diff --git a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql index 9636c7c22db..66ea5e43831 100644 --- a/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql +++ b/python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql @@ -13,23 +13,25 @@ import python import Expressions.CallArgs -from Call call, FunctionObject func, FunctionObject overriding, string problem +from Call call, FunctionValue func, FunctionValue overriding, string problem where -not func.getName() = "__init__" and -overriding.overrides(func) and -call = overriding.getAMethodCall().getNode() and -correct_args_if_called_as_method_objectapi(call, overriding) and -( - arg_count_objectapi(call)+1 < func.minParameters() and problem = "too few arguments" - or - arg_count_objectapi(call) >= func.maxParameters() and problem = "too many arguments" - or - exists(string name | call.getAKeyword().getArg() = name and - overriding.getFunction().getAnArg().(Name).getId() = name and - not func.getFunction().getAnArg().(Name).getId() = name and - problem = "an argument named '" + name + "'" + not func.getName() = "__init__" and + overriding.overrides(func) and + call = overriding.getAMethodCall().getNode() and + correct_args_if_called_as_method(call, overriding) and + ( + arg_count(call) + 1 < func.minParameters() and problem = "too few arguments" + or + arg_count(call) >= func.maxParameters() and problem = "too many arguments" + or + exists(string name | + call.getAKeyword().getArg() = name and + overriding.getScope().getAnArg().(Name).getId() = name and + not func.getScope().getAnArg().(Name).getId() = name and + problem = "an argument named '" + name + "'" + ) ) -) - -select func, "Overridden method signature does not match $@, where it is passed " + problem + ". Overriding method $@ matches the call.", -call, "call", overriding, overriding.descriptiveString() +select func, + "Overridden method signature does not match $@, where it is passed " + problem + + ". Overriding method $@ matches the call.", call, "call", overriding, + overriding.descriptiveString() diff --git a/python/ql/src/Functions/InitIsGenerator.ql b/python/ql/src/Functions/InitIsGenerator.ql index 5ad61ae8255..bb02f103ea3 100644 --- a/python/ql/src/Functions/InitIsGenerator.ql +++ b/python/ql/src/Functions/InitIsGenerator.ql @@ -13,6 +13,7 @@ import python from Function f -where f.isInitMethod() and -(exists(Yield y | y.getScope() = f) or exists(YieldFrom y| y.getScope() = f)) +where + f.isInitMethod() and + (exists(Yield y | y.getScope() = f) or exists(YieldFrom y | y.getScope() = f)) select f, "__init__ method is a generator." diff --git a/python/ql/src/Functions/IterReturnsNonIterator.ql b/python/ql/src/Functions/IterReturnsNonIterator.ql index 67db4e89aa3..405bff78c04 100644 --- a/python/ql/src/Functions/IterReturnsNonIterator.ql +++ b/python/ql/src/Functions/IterReturnsNonIterator.ql @@ -12,18 +12,10 @@ import python -ClassObject return_type(FunctionObject f) { - exists(ControlFlowNode n, Return ret | - ret.getScope() = f.getFunction() and - ret.getValue() = n.getNode() and - n.refersTo(_, result, _) - ) -} - -from ClassObject iterable, FunctionObject iter, ClassObject iterator +from ClassValue iterable, FunctionValue iter, ClassValue iterator where - iter = iterable.lookupAttribute("__iter__") and - iterator = return_type(iter) and + iter = iterable.lookup("__iter__") and + iterator = iter.getAnInferredReturnType() and not iterator.isIterator() select iterator, "Class " + iterator.getName() + diff --git a/python/ql/src/Functions/IterReturnsNonSelf.ql b/python/ql/src/Functions/IterReturnsNonSelf.ql index 0899cf798a1..095685b749a 100644 --- a/python/ql/src/Functions/IterReturnsNonSelf.ql +++ b/python/ql/src/Functions/IterReturnsNonSelf.ql @@ -12,22 +12,19 @@ import python -Function iter_method(ClassObject t) { - result = ((FunctionObject)t.lookupAttribute("__iter__")).getFunction() -} +Function iter_method(ClassValue t) { result = t.lookup("__iter__").(FunctionValue).getScope() } -predicate is_self(Name value, Function f) { - value.getVariable() = ((Name)f.getArg(0)).getVariable() -} +predicate is_self(Name value, Function f) { value.getVariable() = f.getArg(0).(Name).getVariable() } predicate returns_non_self(Function f) { - exists(f.getFallthroughNode()) - or - exists(Return r | r.getScope() = f and not is_self(r.getValue(), f)) - or - exists(Return r | r.getScope() = f and not exists(r.getValue())) + exists(f.getFallthroughNode()) + or + exists(Return r | r.getScope() = f and not is_self(r.getValue(), f)) + or + exists(Return r | r.getScope() = f and not exists(r.getValue())) } -from ClassObject t, Function iter +from ClassValue t, Function iter where t.isIterator() and iter = iter_method(t) and returns_non_self(iter) -select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.", iter, iter.getName() \ No newline at end of file +select t, "Class " + t.getName() + " is an iterator but its $@ method does not return 'self'.", + iter, iter.getName() diff --git a/python/ql/src/Functions/NonCls.ql b/python/ql/src/Functions/NonCls.ql index 983a5c75b30..10ca06af12c 100644 --- a/python/ql/src/Functions/NonCls.ql +++ b/python/ql/src/Functions/NonCls.ql @@ -40,9 +40,11 @@ where ( if exists(f.getArgName(0)) then - message = "Class methods or methods of a type deriving from type should have 'cls', rather than '" - + f.getArgName(0) + "', as their first parameter." + message = + "Class methods or methods of a type deriving from type should have 'cls', rather than '" + + f.getArgName(0) + "', as their first parameter." else - message = "Class methods or methods of a type deriving from type should have 'cls' as their first parameter." + message = + "Class methods or methods of a type deriving from type should have 'cls' as their first parameter." ) select f, message diff --git a/python/ql/src/Functions/NonSelf.ql b/python/ql/src/Functions/NonSelf.ql index 2f0cf44ca2a..a3102eee2aa 100644 --- a/python/ql/src/Functions/NonSelf.ql +++ b/python/ql/src/Functions/NonSelf.ql @@ -45,10 +45,12 @@ where ( if exists(f.getArgName(0)) then - message = "Normal methods should have 'self', rather than '" + f.getArgName(0) + + message = + "Normal methods should have 'self', rather than '" + f.getArgName(0) + "', as their first parameter." else - message = "Normal methods should have at least one parameter (the first of which should be 'self')." + message = + "Normal methods should have at least one parameter (the first of which should be 'self')." ) and not f.hasVarArg() ) and diff --git a/python/ql/src/Functions/OverlyComplexDelMethod.ql b/python/ql/src/Functions/OverlyComplexDelMethod.ql index fff4b3fad0b..b709af7fb11 100644 --- a/python/ql/src/Functions/OverlyComplexDelMethod.ql +++ b/python/ql/src/Functions/OverlyComplexDelMethod.ql @@ -15,7 +15,10 @@ import python -from FunctionObject method -where exists(ClassObject c | c.declaredAttribute("__del__") = method and -method.getFunction().getMetrics().getCyclomaticComplexity() > 3) +from FunctionValue method +where + exists(ClassValue c | + c.declaredAttribute("__del__") = method and + method.getScope().getMetrics().getCyclomaticComplexity() > 3 + ) select method, "Overly complex '__del__' method." diff --git a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql index 9a39e363872..02965c2a3a5 100644 --- a/python/ql/src/Functions/ReturnConsistentTupleSizes.ql +++ b/python/ql/src/Functions/ReturnConsistentTupleSizes.ql @@ -15,15 +15,16 @@ import python predicate returns_tuple_of_size(Function func, int size, AstNode origin) { exists(Return return, TupleValue val | return.getScope() = func and - return.getValue().pointsTo(val, origin) | + return.getValue().pointsTo(val, origin) + | size = val.length() ) } - from Function func, int s1, int s2, AstNode t1, AstNode t2 where returns_tuple_of_size(func, s1, t1) and returns_tuple_of_size(func, s2, t2) and s1 < s2 -select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2, "tuple of size " + s2 +select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2, + "tuple of size " + s2 diff --git a/python/ql/src/Functions/ReturnValueIgnored.ql b/python/ql/src/Functions/ReturnValueIgnored.ql index 19896533a7c..e6d962e594f 100644 --- a/python/ql/src/Functions/ReturnValueIgnored.ql +++ b/python/ql/src/Functions/ReturnValueIgnored.ql @@ -15,34 +15,43 @@ */ import python +import semmle.python.objects.Callables predicate meaningful_return_value(Expr val) { val instanceof Name or val instanceof BooleanLiteral or - exists(FunctionObject callee | val = callee.getACall().getNode() and returns_meaningful_value(callee)) + exists(FunctionValue callee | + val = callee.getACall().getNode() and returns_meaningful_value(callee) + ) or - not exists(FunctionObject callee | val = callee.getACall().getNode()) and not val instanceof Name + not exists(FunctionValue callee | val = callee.getACall().getNode()) and not val instanceof Name } /* Value is used before returning, and thus its value is not lost if ignored */ predicate used_value(Expr val) { - exists(LocalVariable var, Expr other | var.getAnAccess() = val and other = var.getAnAccess() and not other = val) + exists(LocalVariable var, Expr other | + var.getAnAccess() = val and other = var.getAnAccess() and not other = val + ) } -predicate returns_meaningful_value(FunctionObject f) { - not exists(f.getFunction().getFallthroughNode()) - and +predicate returns_meaningful_value(FunctionValue f) { + not exists(f.getScope().getFallthroughNode()) and ( - exists(Return ret, Expr val | ret.getScope() = f.getFunction() and val = ret.getValue() | - meaningful_return_value(val) and - not used_value(val) - ) - or - /* Is f a builtin function that returns something other than None? - * Ignore __import__ as it is often called purely for side effects */ - f.isC() and f.getAnInferredReturnType() != theNoneType() and not f.getName() = "__import__" + exists(Return ret, Expr val | ret.getScope() = f.getScope() and val = ret.getValue() | + meaningful_return_value(val) and + not used_value(val) + ) + or + /* + * Is f a builtin function that returns something other than None? + * Ignore __import__ as it is often called purely for side effects + */ + + f.isBuiltin() and + f.getAnInferredReturnType() != ClassValue::nonetype() and + not f.getName() = "__import__" ) } @@ -55,18 +64,20 @@ predicate wrapped_in_try_except(ExprStmt call) { ) } -from ExprStmt call, FunctionObject callee, float percentage_used, int total -where call.getValue() = callee.getACall().getNode() and returns_meaningful_value(callee) and -not wrapped_in_try_except(call) and -exists(int unused | - unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and - total = count(callee.getACall()) | - percentage_used = (100.0*(total-unused)/total).floor() -) and -/* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ -percentage_used >= 75 and -total >= 5 - -select call, "Call discards return value of function $@. The result is used in " + percentage_used.toString() + "% of calls.", -callee, callee.getName() - +from ExprStmt call, FunctionValue callee, float percentage_used, int total +where + call.getValue() = callee.getACall().getNode() and + returns_meaningful_value(callee) and + not wrapped_in_try_except(call) and + exists(int unused | + unused = count(ExprStmt e | e.getValue().getAFlowNode() = callee.getACall()) and + total = count(callee.getACall()) + | + percentage_used = (100.0 * (total - unused) / total).floor() + ) and + /* Report an alert if we see at least 5 calls and the return value is used in at least 3/4 of those calls. */ + percentage_used >= 75 and + total >= 5 +select call, + "Call discards return value of function $@. The result is used in " + percentage_used.toString() + + "% of calls.", callee, callee.getName() diff --git a/python/ql/src/Functions/SignatureOverriddenMethod.ql b/python/ql/src/Functions/SignatureOverriddenMethod.ql index 47182d8d87d..f24cea3811e 100644 --- a/python/ql/src/Functions/SignatureOverriddenMethod.ql +++ b/python/ql/src/Functions/SignatureOverriddenMethod.ql @@ -6,7 +6,6 @@ * @problem.severity warning * @tags reliability * correctness - * @problem.severity warning * @sub-severity high * @precision very-high * @id py/inheritance/signature-mismatch @@ -15,21 +14,22 @@ import python import Expressions.CallArgs -from FunctionObject base, PyFunctionObject derived +from FunctionValue base, PythonFunctionValue derived where - not exists(base.getACall()) and - not exists(FunctionObject a_derived | - a_derived.overrides(base) and - exists(a_derived.getACall()) - ) and - not derived.getFunction().isSpecialMethod() and - derived.getName() != "__init__" and - derived.isNormalMethod() and - not derived.getFunction().isSpecialMethod() and - // call to overrides distributed for efficiency - ( - (derived.overrides(base) and derived.minParameters() > base.maxParameters()) - or - (derived.overrides(base) and derived.maxParameters() < base.minParameters()) - ) -select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", base, "overridden method" + not exists(base.getACall()) and + not exists(FunctionValue a_derived | + a_derived.overrides(base) and + exists(a_derived.getACall()) + ) and + not derived.getScope().isSpecialMethod() and + derived.getName() != "__init__" and + derived.isNormalMethod() and + not derived.getScope().isSpecialMethod() and + // call to overrides distributed for efficiency + ( + derived.overrides(base) and derived.minParameters() > base.maxParameters() + or + derived.overrides(base) and derived.maxParameters() < base.minParameters() + ) +select derived, "Overriding method '" + derived.getName() + "' has signature mismatch with $@.", + base, "overridden method" diff --git a/python/ql/src/Functions/SignatureSpecialMethods.ql b/python/ql/src/Functions/SignatureSpecialMethods.ql index 3e718ce2a3b..bd5587ec903 100644 --- a/python/ql/src/Functions/SignatureSpecialMethods.ql +++ b/python/ql/src/Functions/SignatureSpecialMethods.ql @@ -12,105 +12,102 @@ import python - predicate is_unary_op(string name) { - name = "__del__" or - name = "__repr__" or - name = "__str__" or - name = "__hash__" or - name = "__bool__" or - name = "__nonzero__" or - name = "__unicode__" or - name = "__len__" or - name = "__iter__" or - name = "__reversed__" or - name = "__neg__" or - name = "__pos__" or - name = "__abs__" or - name = "__invert__" or - name = "__complex__" or - name = "__int__" or - name = "__float__" or - name = "__long__" or - name = "__oct__" or - name = "__hex__" or - name = "__index__" or - name = "__enter__" + name = "__del__" or + name = "__repr__" or + name = "__str__" or + name = "__hash__" or + name = "__bool__" or + name = "__nonzero__" or + name = "__unicode__" or + name = "__len__" or + name = "__iter__" or + name = "__reversed__" or + name = "__neg__" or + name = "__pos__" or + name = "__abs__" or + name = "__invert__" or + name = "__complex__" or + name = "__int__" or + name = "__float__" or + name = "__long__" or + name = "__oct__" or + name = "__hex__" or + name = "__index__" or + name = "__enter__" } predicate is_binary_op(string name) { - name = "__lt__" or - name = "__le__" or - name = "__eq__" or - name = "__ne__" or - name = "__gt__" or - name = "__ge__" or - name = "__cmp__" or - name = "__rcmp__" or - name = "__getattr___" or - name = "__getattribute___" or - name = "__delattr__" or - name = "__delete__" or - name = "__instancecheck__" or - name = "__subclasscheck__" or - name = "__getitem__" or - name = "__delitem__" or - name = "__contains__" or - name = "__add__" or - name = "__sub__" or - name = "__mul__" or - name = "__floordiv__" or - name = "__div__" or - name = "__truediv__" or - name = "__mod__" or - name = "__divmod__" or - name = "__lshift__" or - name = "__rshift__" or - name = "__and__" or - name = "__xor__" or - name = "__or__" or - name = "__radd__" or - name = "__rsub__" or - name = "__rmul__" or - name = "__rfloordiv__" or - name = "__rdiv__" or - name = "__rtruediv__" or - name = "__rmod__" or - name = "__rdivmod__" or - name = "__rpow__" or - name = "__rlshift__" or - name = "__rrshift__" or - name = "__rand__" or - name = "__rxor__" or - name = "__ror__" or - name = "__iadd__" or - name = "__isub__" or - name = "__imul__" or - name = "__ifloordiv__" or - name = "__idiv__" or - name = "__itruediv__" or - name = "__imod__" or - name = "__idivmod__" or - name = "__ipow__" or - name = "__ilshift__" or - name = "__irshift__" or - name = "__iand__" or - name = "__ixor__" or - name = "__ior__" or - name = "__coerce__" + name = "__lt__" or + name = "__le__" or + name = "__eq__" or + name = "__ne__" or + name = "__gt__" or + name = "__ge__" or + name = "__cmp__" or + name = "__rcmp__" or + name = "__getattr___" or + name = "__getattribute___" or + name = "__delattr__" or + name = "__delete__" or + name = "__instancecheck__" or + name = "__subclasscheck__" or + name = "__getitem__" or + name = "__delitem__" or + name = "__contains__" or + name = "__add__" or + name = "__sub__" or + name = "__mul__" or + name = "__floordiv__" or + name = "__div__" or + name = "__truediv__" or + name = "__mod__" or + name = "__divmod__" or + name = "__lshift__" or + name = "__rshift__" or + name = "__and__" or + name = "__xor__" or + name = "__or__" or + name = "__radd__" or + name = "__rsub__" or + name = "__rmul__" or + name = "__rfloordiv__" or + name = "__rdiv__" or + name = "__rtruediv__" or + name = "__rmod__" or + name = "__rdivmod__" or + name = "__rpow__" or + name = "__rlshift__" or + name = "__rrshift__" or + name = "__rand__" or + name = "__rxor__" or + name = "__ror__" or + name = "__iadd__" or + name = "__isub__" or + name = "__imul__" or + name = "__ifloordiv__" or + name = "__idiv__" or + name = "__itruediv__" or + name = "__imod__" or + name = "__idivmod__" or + name = "__ipow__" or + name = "__ilshift__" or + name = "__irshift__" or + name = "__iand__" or + name = "__ixor__" or + name = "__ior__" or + name = "__coerce__" } predicate is_ternary_op(string name) { - name = "__setattr__" or - name = "__set__" or - name = "__setitem__" or - name = "__getslice__" or - name = "__delslice__" + name = "__setattr__" or + name = "__set__" or + name = "__setitem__" or + name = "__getslice__" or + name = "__delslice__" } -predicate is_quad_op(string name) { - name = "__setslice__" or name = "__exit__" -} +predicate is_quad_op(string name) { name = "__setslice__" or name = "__exit__" } int argument_count(PythonFunctionValue f, string name, ClassValue cls) { cls.declaredAttribute(name) = f and @@ -125,52 +122,62 @@ int argument_count(PythonFunctionValue f, string name, ClassValue cls) { ) } -predicate incorrect_special_method_defn(PythonFunctionValue func, string message, boolean show_counts, string name, ClassValue owner) { - exists(int required | - required = argument_count(func, name, owner) | - /* actual_non_default <= actual */ - if required > func.maxParameters() then - (message = "Too few parameters" and show_counts = true) - else if required < func.minParameters() then - (message = "Too many parameters" and show_counts = true) - else if (func.minParameters() < required and not func.getScope().hasVarArg()) then - (message = (required -func.minParameters()) + " default values(s) will never be used" and show_counts = false) - else - none() - ) +predicate incorrect_special_method_defn( + PythonFunctionValue func, string message, boolean show_counts, string name, ClassValue owner +) { + exists(int required | required = argument_count(func, name, owner) | + /* actual_non_default <= actual */ + if required > func.maxParameters() + then message = "Too few parameters" and show_counts = true + else + if required < func.minParameters() + then message = "Too many parameters" and show_counts = true + else + if func.minParameters() < required and not func.getScope().hasVarArg() + then + message = (required - func.minParameters()) + " default values(s) will never be used" and + show_counts = false + else none() + ) } predicate incorrect_pow(FunctionValue func, string message, boolean show_counts, ClassValue owner) { owner.declaredAttribute("__pow__") = func and ( - func.maxParameters() < 2 and message = "Too few parameters" and show_counts = true - or - func.minParameters() > 3 and message = "Too many parameters" and show_counts = true - or - func.minParameters() < 2 and message = (2 - func.minParameters()) + " default value(s) will never be used" and show_counts = false - or - func.minParameters() = 3 and message = "Third parameter to __pow__ should have a default value" and show_counts = false - ) + func.maxParameters() < 2 and message = "Too few parameters" and show_counts = true + or + func.minParameters() > 3 and message = "Too many parameters" and show_counts = true + or + func.minParameters() < 2 and + message = (2 - func.minParameters()) + " default value(s) will never be used" and + show_counts = false + or + func.minParameters() = 3 and + message = "Third parameter to __pow__ should have a default value" and + show_counts = false + ) } predicate incorrect_get(FunctionValue func, string message, boolean show_counts, ClassValue owner) { owner.declaredAttribute("__get__") = func and ( - func.maxParameters() < 3 and message = "Too few parameters" and show_counts = true - or - func.minParameters() > 3 and message = "Too many parameters" and show_counts = true - or - func.minParameters() < 2 and not func.getScope().hasVarArg() and - message = (2 - func.minParameters()) + " default value(s) will never be used" and show_counts = false - ) + func.maxParameters() < 3 and message = "Too few parameters" and show_counts = true + or + func.minParameters() > 3 and message = "Too many parameters" and show_counts = true + or + func.minParameters() < 2 and + not func.getScope().hasVarArg() and + message = (2 - func.minParameters()) + " default value(s) will never be used" and + show_counts = false + ) } string should_have_parameters(PythonFunctionValue f, string name, ClassValue owner) { - exists(int i | i = argument_count(f, name, owner) | - result = i.toString() - ) - or - owner.declaredAttribute(name) = f and (name = "__get__" or name = "__pow__") and result = "2 or 3" + exists(int i | i = argument_count(f, name, owner) | result = i.toString()) + or + owner.declaredAttribute(name) = f and + (name = "__get__" or name = "__pow__") and + result = "2 or 3" } string has_parameters(PythonFunctionValue f) { @@ -183,18 +190,23 @@ string has_parameters(PythonFunctionValue f) { ) } -from PythonFunctionValue f, string message, string sizes, boolean show_counts, string name, ClassValue owner -where - ( - incorrect_special_method_defn(f, message, show_counts, name, owner) - or - incorrect_pow(f, message, show_counts, owner) and name = "__pow__" - or - incorrect_get(f, message, show_counts, owner) and name = "__get__" - ) - and - ( - show_counts = false and sizes = "" or - show_counts = true and sizes = ", which has " + has_parameters(f) + ", but should have " + should_have_parameters(f, name, owner) - ) +from + PythonFunctionValue f, string message, string sizes, boolean show_counts, string name, + ClassValue owner +where + ( + incorrect_special_method_defn(f, message, show_counts, name, owner) + or + incorrect_pow(f, message, show_counts, owner) and name = "__pow__" + or + incorrect_get(f, message, show_counts, owner) and name = "__get__" + ) and + ( + show_counts = false and sizes = "" + or + show_counts = true and + sizes = + ", which has " + has_parameters(f) + ", but should have " + + should_have_parameters(f, name, owner) + ) select f, message + " for special method " + name + sizes + ", in class $@.", owner, owner.getName() diff --git a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql index ab797844533..38632358c08 100644 --- a/python/ql/src/Functions/UseImplicitNoneReturnValue.ql +++ b/python/ql/src/Functions/UseImplicitNoneReturnValue.ql @@ -13,9 +13,11 @@ import python import Testing.Mox predicate is_used(Call c) { - exists(Expr outer | outer != c and outer.containsInScope(c) | outer instanceof Call or outer instanceof Attribute or outer instanceof Subscript) + exists(Expr outer | outer != c and outer.containsInScope(c) | + outer instanceof Call or outer instanceof Attribute or outer instanceof Subscript + ) or - exists(Stmt s | + exists(Stmt s | c = s.getASubExpression() and not s instanceof ExprStmt and /* Ignore if a single return, as def f(): return g() is quite common. Covers implicit return in a lambda. */ @@ -24,11 +26,13 @@ predicate is_used(Call c) { } from Call c, FunctionValue func -where -/* Call result is used, but callee is a procedure */ -is_used(c) and c.getFunc().pointsTo(func) and func.getScope().isProcedure() and -/* All callees are procedures */ -forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and -/* Mox return objects have an `AndReturn` method */ -not useOfMoxInModule(c.getEnclosingModule()) +where + /* Call result is used, but callee is a procedure */ + is_used(c) and + c.getFunc().pointsTo(func) and + func.getScope().isProcedure() and + /* All callees are procedures */ + forall(FunctionValue callee | c.getFunc().pointsTo(callee) | callee.getScope().isProcedure()) and + /* Mox return objects have an `AndReturn` method */ + not useOfMoxInModule(c.getEnclosingModule()) select c, "The result of '$@' is used even though it is always None.", func, func.getQualifiedName() diff --git a/python/ql/src/Imports/DeprecatedModule.ql b/python/ql/src/Imports/DeprecatedModule.ql index 5ecd7f45cfe..359f3dad10d 100644 --- a/python/ql/src/Imports/DeprecatedModule.ql +++ b/python/ql/src/Imports/DeprecatedModule.ql @@ -60,7 +60,8 @@ predicate deprecated_module(string name, string instead, int major, int minor) { string deprecation_message(string mod) { exists(int major, int minor | deprecated_module(mod, _, major, minor) | - result = "The " + mod + " module was deprecated in version " + major.toString() + "." + + result = + "The " + mod + " module was deprecated in version " + major.toString() + "." + minor.toString() + "." ) } @@ -77,8 +78,7 @@ from ImportExpr imp, string name, string instead where name = imp.getName() and deprecated_module(name, instead, _, _) and - not exists(Try try, ExceptStmt except | except = try.getAHandler() - | + not exists(Try try, ExceptStmt except | except = try.getAHandler() | except.getType().pointsTo(ClassValue::importError()) and except.containsInScope(imp) ) diff --git a/python/ql/src/Imports/EncodingError.ql b/python/ql/src/Imports/EncodingError.ql index f26bf8dad33..962ae4426df 100644 --- a/python/ql/src/Imports/EncodingError.ql +++ b/python/ql/src/Imports/EncodingError.ql @@ -13,4 +13,4 @@ import python from EncodingError error -select error, error.getMessage() \ No newline at end of file +select error, error.getMessage() diff --git a/python/ql/src/Imports/ImportShadowedByLoopVar.ql b/python/ql/src/Imports/ImportShadowedByLoopVar.ql index 29f6536cce7..f3817a1bcde 100644 --- a/python/ql/src/Imports/ImportShadowedByLoopVar.ql +++ b/python/ql/src/Imports/ImportShadowedByLoopVar.ql @@ -13,10 +13,13 @@ import python predicate shadowsImport(Variable l) { - exists(Import i, Name shadow | shadow = i.getAName().getAsname() and shadow.getId() = l.getId() and i.getScope() = l.getScope().getScope*()) + exists(Import i, Name shadow | + shadow = i.getAName().getAsname() and + shadow.getId() = l.getId() and + i.getScope() = l.getScope().getScope*() + ) } - from Variable l, Name defn where shadowsImport(l) and defn.defines(l) and exists(For for | defn = for.getTarget()) select defn, "Loop variable '" + l.getId() + "' shadows an import" diff --git a/python/ql/src/Imports/ImportStarUsed.ql b/python/ql/src/Imports/ImportStarUsed.ql index bc125c05a3b..ad25748e771 100644 --- a/python/ql/src/Imports/ImportStarUsed.ql +++ b/python/ql/src/Imports/ImportStarUsed.ql @@ -14,4 +14,3 @@ import python from ImportStar i select i, "Using 'from ... import *' pollutes the namespace" - diff --git a/python/ql/src/Imports/ImportandImportFrom.ql b/python/ql/src/Imports/ImportandImportFrom.ql index 6a12e6b938d..f04e6d896ba 100644 --- a/python/ql/src/Imports/ImportandImportFrom.ql +++ b/python/ql/src/Imports/ImportandImportFrom.ql @@ -12,9 +12,10 @@ import python predicate import_and_import_from(Import i1, Import i2, Module m) { - i1.getEnclosingModule() = i2.getEnclosingModule() and - exists (ImportExpr e1, ImportExpr e2, ImportMember im | - e1 = i1.getAName().getValue() and im = i2.getAName().getValue() and e2 = im.getModule() | + i1.getEnclosingModule() = i2.getEnclosingModule() and + exists(ImportExpr e1, ImportExpr e2, ImportMember im | + e1 = i1.getAName().getValue() and im = i2.getAName().getValue() and e2 = im.getModule() + | e1.getName() = m.getName() and e2.getName() = m.getName() ) } diff --git a/python/ql/src/Imports/Imports.ql b/python/ql/src/Imports/Imports.ql index 7adba83cfe4..233aa7b68be 100644 --- a/python/ql/src/Imports/Imports.ql +++ b/python/ql/src/Imports/Imports.ql @@ -11,16 +11,15 @@ * @id py/multiple-imports-on-line */ -/* Look for imports of the form: -import modA, modB -(Imports should be one per line according PEP 8) -*/ +/* + * Look for imports of the form: + * import modA, modB + * (Imports should be one per line according PEP 8) + */ import python -predicate multiple_import(Import imp) { - count(imp.getAName()) > 1 and not imp.isFromImport() -} +predicate multiple_import(Import imp) { count(imp.getAName()) > 1 and not imp.isFromImport() } from Import i where multiple_import(i) diff --git a/python/ql/src/Imports/ModuleImportsItself.ql b/python/ql/src/Imports/ModuleImportsItself.ql index 1000842550a..3a4ad487687 100644 --- a/python/ql/src/Imports/ModuleImportsItself.ql +++ b/python/ql/src/Imports/ModuleImportsItself.ql @@ -14,7 +14,8 @@ import python predicate modules_imports_itself(ImportingStmt i, ModuleValue m) { i.getEnclosingModule() = m.getScope() and - m = max(string s, ModuleValue m_ | + m = + max(string s, ModuleValue m_ | s = i.getAnImportedModuleName() and m_.importedAs(s) | diff --git a/python/ql/src/Imports/MultipleImports.ql b/python/ql/src/Imports/MultipleImports.ql index 4e5f16779c0..09638457423 100644 --- a/python/ql/src/Imports/MultipleImports.ql +++ b/python/ql/src/Imports/MultipleImports.ql @@ -12,33 +12,35 @@ import python -predicate is_simple_import(Import imp) { - not exists(Attribute a | imp.contains(a)) -} +predicate is_simple_import(Import imp) { not exists(Attribute a | imp.contains(a)) } predicate double_import(Import original, Import duplicate, Module m) { original != duplicate and - is_simple_import(original) and is_simple_import(duplicate) and + is_simple_import(original) and + is_simple_import(duplicate) and /* Imports import the same thing */ - exists (ImportExpr e1, ImportExpr e2 | e1.getName() = m.getName() and e2.getName() = m.getName() and - e1 = original.getAName().getValue() and e2 = duplicate.getAName().getValue() + exists(ImportExpr e1, ImportExpr e2 | + e1.getName() = m.getName() and + e2.getName() = m.getName() and + e1 = original.getAName().getValue() and + e2 = duplicate.getAName().getValue() ) and - original.getAName().getAsname().(Name).getId() = duplicate.getAName().getAsname().(Name).getId() - and + original.getAName().getAsname().(Name).getId() = duplicate.getAName().getAsname().(Name).getId() and exists(Module enclosing | original.getScope() = enclosing and duplicate.getEnclosingModule() = enclosing and ( - /* Duplicate is not at top level scope */ - duplicate.getScope() != enclosing - or - /* Original dominates duplicate */ - original.getAnEntryNode().dominates(duplicate.getAnEntryNode()) + /* Duplicate is not at top level scope */ + duplicate.getScope() != enclosing + or + /* Original dominates duplicate */ + original.getAnEntryNode().dominates(duplicate.getAnEntryNode()) ) - ) + ) } from Import original, Import duplicate, Module m where double_import(original, duplicate, m) -select duplicate, "This import of module " + m.getName() + " is redundant, as it was previously imported $@.", - original, "on line " + original.getLocation().getStartLine().toString() +select duplicate, + "This import of module " + m.getName() + " is redundant, as it was previously imported $@.", + original, "on line " + original.getLocation().getStartLine().toString() diff --git a/python/ql/src/Imports/SyntaxError.ql b/python/ql/src/Imports/SyntaxError.ql index 8a2e0567a04..fd92211d241 100644 --- a/python/ql/src/Imports/SyntaxError.ql +++ b/python/ql/src/Imports/SyntaxError.ql @@ -14,4 +14,4 @@ import python from SyntaxError error where not error instanceof EncodingError -select error, error.getMessage() + " (in Python " + major_version() + ")." \ No newline at end of file +select error, error.getMessage() + " (in Python " + major_version() + ")." diff --git a/python/ql/src/Imports/UnintentionalImport.ql b/python/ql/src/Imports/UnintentionalImport.ql index 8e396896e95..47ae2c999a5 100644 --- a/python/ql/src/Imports/UnintentionalImport.ql +++ b/python/ql/src/Imports/UnintentionalImport.ql @@ -25,8 +25,8 @@ predicate all_defined(ModuleValue exporter) { exporter.getScope().getInitModule().(ImportTimeScope).definesName("__all__") } - from ImportStar imp, ModuleValue exporter where import_star(imp, exporter) and not all_defined(exporter) -select imp, "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", - exporter, exporter.getName() +select imp, + "Import pollutes the enclosing namespace, as the imported module $@ does not define '__all__'.", + exporter, exporter.getName() diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index ac93d9886f1..b8e4903b743 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -62,7 +62,7 @@ private string doctest_in_scope(Scope scope) { } pragma[noinline] -private string typehint_annotation_in_file(File file) { +private string typehint_annotation_in_module(Module module_scope) { exists(StrConst annotation | annotation = any(Arguments a).getAnAnnotation().getASubExpression*() or @@ -71,7 +71,7 @@ private string typehint_annotation_in_file(File file) { annotation = any(FunctionExpr f).getReturns().getASubExpression*() | annotation.pointsTo(Value::forString(result)) and - file = annotation.getLocation().getFile() + annotation.getEnclosingModule() = module_scope ) } @@ -84,17 +84,19 @@ private string typehint_comment_in_file(File file) { ) } -predicate imported_module_used_in_typehint(Import imp) { - exists(string modname, File file | - imp.getAName().getAsname().(Name).getId() = modname and - file = imp.getScope().(Module).getFile() +/** Holds if the imported alias `name` from `imp` is used in a typehint (in the same file as `imp`) */ +predicate imported_alias_used_in_typehint(Import imp, Variable name) { + imp.getAName().getAsname().(Name).getVariable() = name and + exists(File file, Module module_scope | + module_scope = imp.getEnclosingModule() and + file = module_scope.getFile() | // Look for type hints containing the patterns: // # type: …name… - typehint_comment_in_file(file).regexpMatch("# type:.*" + modname + ".*") + typehint_comment_in_file(file).regexpMatch("# type:.*" + name.getId() + ".*") or // Type hint is inside a string annotation, as needed for forward references - typehint_annotation_in_file(file).regexpMatch(".*\\b" + modname + "\\b.*") + typehint_annotation_in_module(module_scope).regexpMatch(".*\\b" + name.getId() + "\\b.*") ) } @@ -114,7 +116,7 @@ predicate unused_import(Import imp, Variable name) { // Assume that opaque `__all__` includes imported module not all_not_understood(imp.getEnclosingModule()) and not imported_module_used_in_doctest(imp) and - not imported_module_used_in_typehint(imp) and + not imported_alias_used_in_typehint(imp, name) and // Only consider import statements that actually point-to something (possibly an unknown module). // If this is not the case, it's likely that the import statement never gets executed. imp.getAName().getValue().pointsTo(_) diff --git a/python/ql/src/Lexical/CommentedOutCode.ql b/python/ql/src/Lexical/CommentedOutCode.ql index 5b71bd2fe0a..d40ce95598a 100644 --- a/python/ql/src/Lexical/CommentedOutCode.ql +++ b/python/ql/src/Lexical/CommentedOutCode.ql @@ -12,7 +12,6 @@ */ import python - import Lexical.CommentedOutCode from CommentedOutCodeBlock c diff --git a/python/ql/src/Lexical/CommentedOutCode.qll b/python/ql/src/Lexical/CommentedOutCode.qll index dbb12867466..e8076092ded 100644 --- a/python/ql/src/Lexical/CommentedOutCode.qll +++ b/python/ql/src/Lexical/CommentedOutCode.qll @@ -1,6 +1,5 @@ import python - private predicate def_statement(Comment c) { c.getText().regexpMatch("#(\\S*\\s+)?def\\s.*\\(.*\\).*:\\s*(#.*)?") } @@ -12,7 +11,7 @@ private predicate if_statement(Comment c) { } private predicate for_statement(Comment c) { - c.getText().regexpMatch("#(\\S*\\s+)?for\\s.*\\sin\\s.*:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?for\\s.*\\sin\\s.*:\\s*(#.*)?") } private predicate with_statement(Comment c) { @@ -20,11 +19,11 @@ private predicate with_statement(Comment c) { } private predicate try_statement(Comment c) { - c.getText().regexpMatch("#(\\S*\\s+)?try:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?try:\\s*(#.*)?") or c.getText().regexpMatch("#(\\S*\\s+)?except\\s*(\\w+\\s*(\\sas\\s+\\w+\\s*)?)?:\\s*(#.*)?") or - c.getText().regexpMatch("#(\\S*\\s+)?finally:\\s*(#.*)?") + c.getText().regexpMatch("#(\\S*\\s+)?finally:\\s*(#.*)?") } private int indentation(Comment c) { @@ -39,18 +38,16 @@ private predicate class_statement(Comment c) { c.getText().regexpMatch("#(\\S*\\s+)?class\\s+\\w+.*:\\s*(#.*)?") } -private predicate triple_quote(Comment c) { - c.getText().regexpMatch("#.*(\"\"\"|''').*") -} +private predicate triple_quote(Comment c) { c.getText().regexpMatch("#.*(\"\"\"|''').*") } private predicate triple_quoted_string_part(Comment start, Comment end) { - triple_quote(start) and end = start - or - exists(Comment mid | + triple_quote(start) and end = start + or + exists(Comment mid | triple_quoted_string_part(start, mid) and end = non_empty_following(mid) and not triple_quote(end) - ) + ) } private predicate maybe_code(Comment c) { @@ -59,41 +56,37 @@ private predicate maybe_code(Comment c) { commented_out_comment(c) } -private predicate commented_out_comment(Comment c) { - c.getText().regexpMatch("#+\\s+#.*") -} +private predicate commented_out_comment(Comment c) { c.getText().regexpMatch("#+\\s+#.*") } private int scope_start(Comment start) { ( - def_statement(start) or - class_statement(start) - ) - and - result = indentation(start) - and + def_statement(start) or + class_statement(start) + ) and + result = indentation(start) and not non_code(start) } private int block_start(Comment start) { ( - if_statement(start) or - for_statement(start) or - try_statement(start) or - with_statement(start) - ) - and - result = indentation(start) - and + if_statement(start) or + for_statement(start) or + try_statement(start) or + with_statement(start) + ) and + result = indentation(start) and not non_code(start) } private int scope_doc_string_part(Comment start, Comment end) { result = scope_start(start) and - triple_quote(end) and end = non_empty_following(start) + triple_quote(end) and + end = non_empty_following(start) or - exists(Comment mid | + exists(Comment mid | result = scope_doc_string_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | not triple_quote(end) ) } @@ -101,15 +94,16 @@ private int scope_doc_string_part(Comment start, Comment end) { private int scope_part(Comment start, Comment end) { result = scope_start(start) and end = start or - exists(Comment mid | + exists(Comment mid | result = scope_doc_string_part(start, mid) and end = non_empty_following(mid) and triple_quote(end) ) or - exists(Comment mid | + exists(Comment mid | result = scope_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | indentation(end) > result ) } @@ -119,9 +113,10 @@ private int block_part(Comment start, Comment end) { end = non_empty_following(start) and indentation(end) > result or - exists(Comment mid | + exists(Comment mid | result = block_part(start, mid) and - end = non_empty_following(mid) | + end = non_empty_following(mid) + | indentation(end) > result or result = block_start(end) @@ -145,13 +140,11 @@ private predicate commented_out_code(Comment c) { } private predicate commented_out_code_part(Comment start, Comment end) { - commented_out_code(start) and end = start and - not exists(Comment prev | - non_empty_following(prev) = start | - commented_out_code(prev) - ) + commented_out_code(start) and + end = start and + not exists(Comment prev | non_empty_following(prev) = start | commented_out_code(prev)) or - exists(Comment mid | + exists(Comment mid | commented_out_code_part(start, mid) and non_empty_following(mid) = end and commented_out_code(end) @@ -167,12 +160,7 @@ private predicate commented_out_code_block(Comment start, Comment end) { /* A single line comment that appears to be commented out code */ class CommentedOutCodeLine extends Comment { - - CommentedOutCodeLine () { - exists(CommentedOutCodeBlock b | - b.contains(this) - ) - } + CommentedOutCodeLine() { exists(CommentedOutCodeBlock b | b.contains(this)) } /* Whether this commented-out code line is likely to be example code embedded in a larger comment. */ predicate maybeExampleCode() { @@ -181,19 +169,13 @@ class CommentedOutCodeLine extends Comment { block.maybeExampleCode() ) } - } /** A block of comments that appears to be commented out code */ class CommentedOutCodeBlock extends @py_comment { - - CommentedOutCodeBlock() { - commented_out_code_block(this, _) - } + CommentedOutCodeBlock() { commented_out_code_block(this, _) } - string toString() { - result = "Commented out code" - } + string toString() { result = "Commented out code" } /** Whether this commented-out code block contains the comment c */ predicate contains(Comment c) { @@ -207,28 +189,22 @@ class CommentedOutCodeBlock extends @py_comment { } /** The length of this comment block (in comments) */ - int length() { - result = count(Comment c | this.contains(c)) - } + int length() { result = count(Comment c | this.contains(c)) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - ((Comment)this).getLocation().hasLocationInfo(filepath, bl, bc, _, _) - and - exists(Comment end | - commented_out_code_block(this, end) | + this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and + exists(Comment end | commented_out_code_block(this, end) | end.getLocation().hasLocationInfo(_, _, _, el, ec) ) } /** Whether this commented-out code block is likely to be example code embedded in a larger comment. */ predicate maybeExampleCode() { - exists(CommentBlock block | - block.contains((Comment)this) | + exists(CommentBlock block | block.contains(this.(Comment)) | exists(int all_code | - all_code = sum (CommentedOutCodeBlock code | block.contains((Comment)code) | code.length()) - and + all_code = sum(CommentedOutCodeBlock code | block.contains(code.(Comment)) | code.length()) and /* This ratio may need fine tuning */ - block.length() > all_code*2 + block.length() > all_code * 2 ) ) } @@ -239,13 +215,14 @@ private predicate word_pair(Comment c, string s1, string s2) { exists(int i1, int i2, int o1, int o2 | s1 = c.getText().regexpFind("\\w+", i1, o1) and s2 = c.getText().regexpFind("\\w+", i2, o2) and - i2 = i1 + 1 and + i2 = i1 + 1 and c.getText().prefix(o1).regexpMatch("[^'\"]*") and c.getText().substring(o1 + s1.length(), o2).regexpMatch("\\s+") ) } -/** The comment c cannot be code if it contains a word pair "word1 word2" and +/** + * The comment c cannot be code if it contains a word pair "word1 word2" and * either: * 1. word1 is not a keyword and word2 is not an operator: * "x is" could be code, "return y" could be code, but "isnt code" cannot be code. @@ -257,48 +234,44 @@ private predicate non_code(Comment c) { exists(string word1, string word2 | word_pair(c, word1, word2) and not word2 = operator_keyword() - | + | not word1 = a_keyword() or word1 = keyword_requiring_colon() and not c.getText().matches("%:%") ) and /* Except comments of the form: # (maybe code) # some comment */ - not c.getText().regexpMatch("#\\S+\\s.*#.*") + not c.getText().regexpMatch("#\\S+\\s.*#.*") or /* Don't count doctests as code */ - c.getText().matches("%>>>%") or c.getText().matches("%...%") + c.getText().matches("%>>>%") + or + c.getText().matches("%...%") } -private predicate filler(Comment c) { - c.getText().regexpMatch("#+[\\s*#-_=+]*") -} +private predicate filler(Comment c) { c.getText().regexpMatch("#+[\\s*#-_=+]*") } -/** Gets the first non empty comment following c */ +/** Gets the first non empty comment following c */ private Comment non_empty_following(Comment c) { - not empty(result) and - ( + not empty(result) and + ( result = empty_following(c).getFollowing() or - not empty(c) and result = c.getFollowing() - ) + not empty(c) and result = c.getFollowing() + ) } /* Helper for non_empty_following() */ private Comment empty_following(Comment c) { not empty(c) and - empty(result) - and - exists(Comment prev | - result = prev.getFollowing() | + empty(result) and + exists(Comment prev | result = prev.getFollowing() | prev = c or prev = empty_following(c) ) } -private predicate empty(Comment c) { - c.getText().regexpMatch("#+\\s*") -} +private predicate empty(Comment c) { c.getText().regexpMatch("#+\\s*") } /* A comment following code on the same line */ private predicate endline_comment(Comment c) { @@ -315,21 +288,40 @@ private predicate file_or_url(Comment c) { } private string operator_keyword() { - result = "import" or result = "and" or result = "is" or result = "or" or result = "in" or result = "not" or result = "as" + result = "import" or + result = "and" or + result = "is" or + result = "or" or + result = "in" or + result = "not" or + result = "as" } private string keyword_requiring_colon() { - result = "try" or result = "while" or result = "elif" or result = "else" or result = "if" or - result = "except" or result = "def" or result = "class" + result = "try" or + result = "while" or + result = "elif" or + result = "else" or + result = "if" or + result = "except" or + result = "def" or + result = "class" } - + private string other_keyword() { - result = "del" or result = "lambda" or result = "from" or - result = "global" or result = "with" or result = "assert" or - result = "yield" or result = "finally" or - result = "print" or - result = "exec" or result = "raise" or - result = "return" or result = "for" + result = "del" or + result = "lambda" or + result = "from" or + result = "global" or + result = "with" or + result = "assert" or + result = "yield" or + result = "finally" or + result = "print" or + result = "exec" or + result = "raise" or + result = "return" or + result = "for" } private string a_keyword() { diff --git a/python/ql/src/Lexical/FCommentedOutCode.ql b/python/ql/src/Lexical/FCommentedOutCode.ql index 2f6ee0741c6..e988f4074c7 100644 --- a/python/ql/src/Lexical/FCommentedOutCode.ql +++ b/python/ql/src/Lexical/FCommentedOutCode.ql @@ -11,10 +11,8 @@ import python import Lexical.CommentedOutCode - import python from File f, int n where n = count(CommentedOutCodeLine c | not c.maybeExampleCode() and c.getLocation().getFile() = f) -select f, n -order by n desc +select f, n order by n desc diff --git a/python/ql/src/Lexical/OldOctalLiteral.ql b/python/ql/src/Lexical/OldOctalLiteral.ql index af0ee723c10..28791d8903d 100644 --- a/python/ql/src/Lexical/OldOctalLiteral.ql +++ b/python/ql/src/Lexical/OldOctalLiteral.ql @@ -12,8 +12,7 @@ import python predicate is_old_octal(IntegerLiteral i) { - exists(string text | - text = i.getText() | + exists(string text | text = i.getText() | text.charAt(0) = "0" and not text = "00" and exists(text.charAt(1).toInt()) and diff --git a/python/ql/src/Metrics/CLinesOfCode.ql b/python/ql/src/Metrics/CLinesOfCode.ql index 5c5453fb76a..c7b29615593 100644 --- a/python/ql/src/Metrics/CLinesOfCode.ql +++ b/python/ql/src/Metrics/CLinesOfCode.ql @@ -8,8 +8,8 @@ * @metricAggregate avg sum max * @tags maintainability */ + import python from Function f -select f, f.getMetrics().getNumberOfLinesOfCode() as n -order by n desc \ No newline at end of file +select f, f.getMetrics().getNumberOfLinesOfCode() as n order by n desc diff --git a/python/ql/src/Metrics/ClassAfferentCoupling.ql b/python/ql/src/Metrics/ClassAfferentCoupling.ql index 5fd2ec4c16f..295e8c61a6c 100644 --- a/python/ql/src/Metrics/ClassAfferentCoupling.ql +++ b/python/ql/src/Metrics/ClassAfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ClassMetrics cls -select cls, cls.getAfferentCoupling() as n -order by n desc - +select cls, cls.getAfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/ClassEfferentCoupling.ql b/python/ql/src/Metrics/ClassEfferentCoupling.ql index d8d9dabd5dd..d960c0142e3 100644 --- a/python/ql/src/Metrics/ClassEfferentCoupling.ql +++ b/python/ql/src/Metrics/ClassEfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ClassMetrics cls -select cls, cls.getEfferentCoupling() as n -order by n desc - +select cls, cls.getEfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/CommentRatio.ql b/python/ql/src/Metrics/CommentRatio.ql index 3f04da28283..76a185321ac 100644 --- a/python/ql/src/Metrics/CommentRatio.ql +++ b/python/ql/src/Metrics/CommentRatio.ql @@ -10,9 +10,10 @@ * @tags maintainability * documentation */ + import python from Module m, ModuleMetrics mm where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfComments() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc +select m, 100.0 * (mm.getNumberOfLinesOfComments().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/src/Metrics/CyclomaticComplexity.ql b/python/ql/src/Metrics/CyclomaticComplexity.ql index c5ab9858202..1e332f4ec9f 100644 --- a/python/ql/src/Metrics/CyclomaticComplexity.ql +++ b/python/ql/src/Metrics/CyclomaticComplexity.ql @@ -11,9 +11,9 @@ * complexity * maintainability */ + import python from Function func, int complexity where complexity = func.getMetrics().getCyclomaticComplexity() -select func, complexity -order by complexity desc \ No newline at end of file +select func, complexity order by complexity desc diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql index 49506b0a0f9..b2c319070ea 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependencies.ql @@ -2,7 +2,7 @@ * @name External dependencies * @description Count the number of dependencies that a Python source file has on external packages. * @kind treemap - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType externalDependency * @precision medium * @id py/external-dependencies @@ -11,18 +11,18 @@ import python import semmle.python.dependencies.TechInventory -/* +/* * These two columns encode four logical columns: - * + * * 1. Python source file where the dependency originates * 2. Package Object, ideally referring to a PyPI or similar externally provided package * 3. Version of that package Object, if known * 4. Number of dependencies from the source file to the package - * + * * Ideally this query would therefore return three columns, * but this would require changing the dashboard database schema * and dashboard extractor. - * + * * The first column (the Python source file) is prepended with a '/' * so that the file path matches the path used for the file in the * dashboard database, which is implicitly relative to the source @@ -30,15 +30,15 @@ import semmle.python.dependencies.TechInventory */ predicate src_package_count(File sourceFile, ExternalPackage package, int total) { - total = strictcount(AstNode src | - dependency(src, package) and - src.getLocation().getFile() = sourceFile - ) + total = + strictcount(AstNode src | + dependency(src, package) and + src.getLocation().getFile() = sourceFile + ) } from File sourceFile, int total, string entity, ExternalPackage package -where -src_package_count(sourceFile, package, total) and -entity = munge(sourceFile, package) -select entity, total -order by total desc +where + src_package_count(sourceFile, package, total) and + entity = munge(sourceFile, package) +select entity, total order by total desc diff --git a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql index 3129edd6328..2424d82abeb 100644 --- a/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql +++ b/python/ql/src/Metrics/Dependencies/ExternalDependenciesSourceLinks.ql @@ -16,11 +16,12 @@ import semmle.python.dependencies.TechInventory * recover that information once we are in the dashboard database, using the * ExternalEntity.getASourceLink() method. */ + from File sourceFile, string entity where - exists(PackageObject package, AstNode src | - dependency(src, package) and - src.getLocation().getFile() = sourceFile and - entity = munge(sourceFile, package) - ) + exists(PackageObject package, AstNode src | + dependency(src, package) and + src.getLocation().getFile() = sourceFile and + entity = munge(sourceFile, package) + ) select entity, sourceFile diff --git a/python/ql/src/Metrics/DirectImports.ql b/python/ql/src/Metrics/DirectImports.ql index ec9114cddd9..240cd65e687 100644 --- a/python/ql/src/Metrics/DirectImports.ql +++ b/python/ql/src/Metrics/DirectImports.ql @@ -9,6 +9,7 @@ * @tags modularity * maintainability */ + import python from ModuleValue m, int n diff --git a/python/ql/src/Metrics/DocStringRatio.ql b/python/ql/src/Metrics/DocStringRatio.ql index 43d8d7af248..46859560c16 100644 --- a/python/ql/src/Metrics/DocStringRatio.ql +++ b/python/ql/src/Metrics/DocStringRatio.ql @@ -9,9 +9,11 @@ * @tags maintainability * documentation */ + import python from Module m, ModuleMetrics mm -where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfDocStrings() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc +where mm = m.getMetrics() and mm.getNumberOfLines() > 0 +select m, + 100.0 * (mm.getNumberOfLinesOfDocStrings().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/src/Metrics/External/CommitDisplayStrings.ql b/python/ql/src/Metrics/External/CommitDisplayStrings.ql index dd5104996d0..a682f4d1de6 100644 --- a/python/ql/src/Metrics/External/CommitDisplayStrings.ql +++ b/python/ql/src/Metrics/External/CommitDisplayStrings.ql @@ -4,7 +4,9 @@ * @id py/commit-display-strings * @metricType commit */ + import python import external.VCS + from Commit c select c.getRevisionName(), c.getMessage() + "(" + c.getDate().toString() + ")" diff --git a/python/ql/src/Metrics/External/CommitSourceLinks.ql b/python/ql/src/Metrics/External/CommitSourceLinks.ql index a31b73e2a7c..607829288c6 100644 --- a/python/ql/src/Metrics/External/CommitSourceLinks.ql +++ b/python/ql/src/Metrics/External/CommitSourceLinks.ql @@ -4,8 +4,10 @@ * @id py/commit-source-links * @metricType commit */ + import python import external.VCS + from Commit c, File f where f.fromSource() and f = c.getAnAffectedFile() select c.getRevisionName(), f diff --git a/python/ql/src/Metrics/FClasses.ql b/python/ql/src/Metrics/FClasses.ql index da667bd1df5..4736021caf2 100644 --- a/python/ql/src/Metrics/FClasses.ql +++ b/python/ql/src/Metrics/FClasses.ql @@ -13,5 +13,4 @@ import python from Module m, int n where n = count(Class c | c.getEnclosingModule() = m) -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FFunctionsAndMethods.ql b/python/ql/src/Metrics/FFunctionsAndMethods.ql index b8d3a43b1dd..5b9fdf799cf 100644 --- a/python/ql/src/Metrics/FFunctionsAndMethods.ql +++ b/python/ql/src/Metrics/FFunctionsAndMethods.ql @@ -13,5 +13,4 @@ import python from Module m, int n where n = count(Function f | f.getEnclosingModule() = m and f.getName() != "lambda") -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLines.ql b/python/ql/src/Metrics/FLines.ql index 04d9abad7e4..340fb6f58ea 100644 --- a/python/ql/src/Metrics/FLines.ql +++ b/python/ql/src/Metrics/FLines.ql @@ -7,9 +7,9 @@ * @metricType file * @metricAggregate avg sum max */ + import python from Module m, int n where n = m.getMetrics().getNumberOfLines() -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfCode.ql b/python/ql/src/Metrics/FLinesOfCode.ql index 778897c6ae0..a46698c7087 100644 --- a/python/ql/src/Metrics/FLinesOfCode.ql +++ b/python/ql/src/Metrics/FLinesOfCode.ql @@ -10,9 +10,9 @@ * @tags maintainability * @id py/lines-of-code-in-files */ + import python from Module m, int n where n = m.getMetrics().getNumberOfLinesOfCode() -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfComments.ql b/python/ql/src/Metrics/FLinesOfComments.ql index 38b19c2dc46..bd52f8d5caa 100644 --- a/python/ql/src/Metrics/FLinesOfComments.ql +++ b/python/ql/src/Metrics/FLinesOfComments.ql @@ -9,9 +9,10 @@ * @precision very-high * @id py/lines-of-comments-in-files */ + import python from Module m, int n -where n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings() -select m, n -order by n desc +where + n = m.getMetrics().getNumberOfLinesOfComments() + m.getMetrics().getNumberOfLinesOfDocStrings() +select m, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql index ac8e0a3a25c..03bee534ee3 100644 --- a/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql +++ b/python/ql/src/Metrics/FLinesOfDuplicatedCode.ql @@ -10,17 +10,17 @@ * @tags testability * @id py/duplicated-lines-in-files */ + import python import external.CodeDuplication - + from File f, int n - -where n = count(int line | - exists(DuplicateBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()] and - not whitelistedLineForDuplication(f, line) - ) -) - -select f, n -order by n desc +where + n = + count(int line | + exists(DuplicateBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] and + not whitelistedLineForDuplication(f, line) + ) + ) +select f, n order by n desc diff --git a/python/ql/src/Metrics/FLinesOfSimilarCode.ql b/python/ql/src/Metrics/FLinesOfSimilarCode.ql index e78fe52959b..d407a38d63d 100644 --- a/python/ql/src/Metrics/FLinesOfSimilarCode.ql +++ b/python/ql/src/Metrics/FLinesOfSimilarCode.ql @@ -10,17 +10,17 @@ * @tags testability * @id py/similar-lines-in-files */ + import python import external.CodeDuplication - + from File f, int n - -where n = count(int line | - exists(SimilarBlock d | d.sourceFile() = f | - line in [d.sourceStartLine()..d.sourceEndLine()] and - not whitelistedLineForDuplication(f, line) - ) -) - -select f, n -order by n desc +where + n = + count(int line | + exists(SimilarBlock d | d.sourceFile() = f | + line in [d.sourceStartLine() .. d.sourceEndLine()] and + not whitelistedLineForDuplication(f, line) + ) + ) +select f, n order by n desc diff --git a/python/ql/src/Metrics/FNumberOfTests.ql b/python/ql/src/Metrics/FNumberOfTests.ql index 1cc914a0d55..34a76c70d33 100644 --- a/python/ql/src/Metrics/FNumberOfTests.ql +++ b/python/ql/src/Metrics/FNumberOfTests.ql @@ -6,13 +6,12 @@ * @metricType file * @metricAggregate avg sum max * @precision medium - * @precision very-high * @id py/tests-in-files */ + import python import semmle.python.filters.Tests from Module m, int n where n = strictcount(Test test | test.getEnclosingModule() = m) -select m.getFile(), n -order by n desc +select m.getFile(), n order by n desc diff --git a/python/ql/src/Metrics/FunctionNumberOfCalls.ql b/python/ql/src/Metrics/FunctionNumberOfCalls.ql index 0dd5050214a..fb4dfe5a9d2 100644 --- a/python/ql/src/Metrics/FunctionNumberOfCalls.ql +++ b/python/ql/src/Metrics/FunctionNumberOfCalls.ql @@ -3,14 +3,12 @@ * @description The total number of calls in a function. * @kind treemap * @id py/number-of-calls-per-function - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType callable * @metricAggregate avg max */ import python - from FunctionMetrics func -select func, func.getNumberOfCalls() as n -order by n desc +select func, func.getNumberOfCalls() as n order by n desc diff --git a/python/ql/src/Metrics/FunctionStatementNestingDepth.ql b/python/ql/src/Metrics/FunctionStatementNestingDepth.ql index 64a72fbd34d..ab40cc6068d 100644 --- a/python/ql/src/Metrics/FunctionStatementNestingDepth.ql +++ b/python/ql/src/Metrics/FunctionStatementNestingDepth.ql @@ -12,7 +12,5 @@ import python - from FunctionMetrics func -select func, func.getStatementNestingDepth() as n -order by n desc +select func, func.getStatementNestingDepth() as n order by n desc diff --git a/python/ql/src/Metrics/History/HChurn.ql b/python/ql/src/Metrics/History/HChurn.ql index 437fae7460c..e18b8dd528a 100644 --- a/python/ql/src/Metrics/History/HChurn.ql +++ b/python/ql/src/Metrics/History/HChurn.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentChurnForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentChurnForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HLinesAdded.ql b/python/ql/src/Metrics/History/HLinesAdded.ql index 9eea8687118..239d227f365 100644 --- a/python/ql/src/Metrics/History/HLinesAdded.ql +++ b/python/ql/src/Metrics/History/HLinesAdded.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentAdditionsForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentAdditionsForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HLinesDeleted.ql b/python/ql/src/Metrics/History/HLinesDeleted.ql index 905d15b524c..7f02c17cc2c 100644 --- a/python/ql/src/Metrics/History/HLinesDeleted.ql +++ b/python/ql/src/Metrics/History/HLinesDeleted.ql @@ -7,11 +7,17 @@ * @metricType file * @metricAggregate avg sum max */ + import python import external.VCS from Module m, int n -where n = sum(Commit entry, int churn | churn = entry.getRecentDeletionsForFile(m.getFile()) and not artificialChange(entry) | churn) - and exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, n -order by n desc +where + n = + sum(Commit entry, int churn | + churn = entry.getRecentDeletionsForFile(m.getFile()) and not artificialChange(entry) + | + churn + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) +select m, n order by n desc diff --git a/python/ql/src/Metrics/History/HNumberOfAuthors.ql b/python/ql/src/Metrics/History/HNumberOfAuthors.ql index fef769fc705..15e679e58c5 100644 --- a/python/ql/src/Metrics/History/HNumberOfAuthors.ql +++ b/python/ql/src/Metrics/History/HNumberOfAuthors.ql @@ -7,10 +7,10 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) select m, count(Author author | author.getAnEditedFile() = m.getFile()) - diff --git a/python/ql/src/Metrics/History/HNumberOfCoCommits.ql b/python/ql/src/Metrics/History/HNumberOfCoCommits.ql index 81dbe8ba2da..4f48641e394 100644 --- a/python/ql/src/Metrics/History/HNumberOfCoCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfCoCommits.ql @@ -7,14 +7,17 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS -int committedFiles(Commit commit) { - result = count(commit.getAnAffectedFile()) -} +int committedFiles(Commit commit) { result = count(commit.getAnAffectedFile()) } from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, avg(Commit commit, int toAvg | (commit.getAnAffectedFile() = m.getFile()) and (toAvg = committedFiles(commit)-1) | toAvg) - +select m, + avg(Commit commit, int toAvg | + commit.getAnAffectedFile() = m.getFile() and toAvg = committedFiles(commit) - 1 + | + toAvg + ) diff --git a/python/ql/src/Metrics/History/HNumberOfCommits.ql b/python/ql/src/Metrics/History/HNumberOfCommits.ql index deca31e1444..d7f99646fe3 100644 --- a/python/ql/src/Metrics/History/HNumberOfCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfCommits.ql @@ -7,6 +7,7 @@ * @metricType commit * @metricAggregate sum */ + import python import external.VCS diff --git a/python/ql/src/Metrics/History/HNumberOfReCommits.ql b/python/ql/src/Metrics/History/HNumberOfReCommits.ql index f5831944aed..c1863e934c9 100644 --- a/python/ql/src/Metrics/History/HNumberOfReCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfReCommits.ql @@ -5,25 +5,30 @@ * @id py/historical-number-of-re-commits * @treemap.warnOn highValues * @metricType file - * @metricAggregate avg min max + * @metricAggregate avg min max */ + import python import external.VCS predicate inRange(Commit first, Commit second) { - first.getAnAffectedFile() = second.getAnAffectedFile() and - first != second and - exists(int n | n = first.getDate().daysTo(second.getDate()) and - n >= 0 and n < 5) + first.getAnAffectedFile() = second.getAnAffectedFile() and + first != second and + exists(int n | + n = first.getDate().daysTo(second.getDate()) and + n >= 0 and + n < 5 + ) } int recommitsForFile(File f) { - result = count(Commit recommit | - f = recommit.getAnAffectedFile() and - exists(Commit prev | inRange(prev, recommit))) + result = + count(Commit recommit | + f = recommit.getAnAffectedFile() and + exists(Commit prev | inRange(prev, recommit)) + ) } from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) select m, recommitsForFile(m.getFile()) - diff --git a/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql b/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql index 6ea84550f76..75832cc82bd 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentAuthors.ql @@ -7,10 +7,18 @@ * @metricType file * @metricAggregate avg min max */ + import python import external.VCS from Module m where exists(m.getMetrics().getNumberOfLinesOfCode()) -select m, count(Author author | exists(Commit e | e = author.getACommit() and m.getFile() = e.getAnAffectedFile() and e.daysToNow() <= 180 and not artificialChange(e))) - +select m, + count(Author author | + exists(Commit e | + e = author.getACommit() and + m.getFile() = e.getAnAffectedFile() and + e.daysToNow() <= 180 and + not artificialChange(e) + ) + ) diff --git a/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql b/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql index 3f35a9cba77..9b90a73294f 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentChangedFiles.ql @@ -5,13 +5,16 @@ * @id py/historical-number-of-recent-changed-files * @treemap.warnOn highValues * @metricType file - * @metricAggregate avg min max + * @metricAggregate avg min max */ + import python import external.VCS from Module m -where exists(Commit e | e.getAnAffectedFile() = m.getFile() and e.daysToNow() <= 180 and not artificialChange(e)) - and exists(m.getMetrics().getNumberOfLinesOfCode()) +where + exists(Commit e | + e.getAnAffectedFile() = m.getFile() and e.daysToNow() <= 180 and not artificialChange(e) + ) and + exists(m.getMetrics().getNumberOfLinesOfCode()) select m, 1 - diff --git a/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql b/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql index e9e3b14538f..7ebec9bb7a4 100644 --- a/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql +++ b/python/ql/src/Metrics/History/HNumberOfRecentCommits.ql @@ -7,10 +7,10 @@ * @metricType commit * @metricAggregate sum */ + import python import external.VCS from Commit c where c.daysToNow() <= 180 and not artificialChange(c) select c.getRevisionName(), 1 - diff --git a/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql b/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql index 47a6f20db3e..3f4790272d2 100644 --- a/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql +++ b/python/ql/src/Metrics/Internal/CallableDisplayStrings.ql @@ -4,6 +4,7 @@ * @id py/function-display-strings * @metricType callable */ + import python from Function f diff --git a/python/ql/src/Metrics/Internal/CallableExtents.ql b/python/ql/src/Metrics/Internal/CallableExtents.ql index 7e2d0baedfa..be617bf2e44 100644 --- a/python/ql/src/Metrics/Internal/CallableExtents.ql +++ b/python/ql/src/Metrics/Internal/CallableExtents.ql @@ -4,6 +4,7 @@ * @id py/function-extents * @metricType callable */ + import python import Extents diff --git a/python/ql/src/Metrics/Internal/CallableSourceLinks.ql b/python/ql/src/Metrics/Internal/CallableSourceLinks.ql index 41278a18684..0e37d683222 100644 --- a/python/ql/src/Metrics/Internal/CallableSourceLinks.ql +++ b/python/ql/src/Metrics/Internal/CallableSourceLinks.ql @@ -4,6 +4,7 @@ * @id py/function-source-links * @metricType callable */ + import python from Function f diff --git a/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql b/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql index 612abfebec7..cf240b42af1 100644 --- a/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql +++ b/python/ql/src/Metrics/Internal/ClassDisplayStrings.ql @@ -4,6 +4,7 @@ * @id py/lgtm/class-display-strings * @metricType reftype */ + import python from Class c diff --git a/python/ql/src/Metrics/Internal/ClassExtents.ql b/python/ql/src/Metrics/Internal/ClassExtents.ql index cc5fd7e9390..b3b3985a8a8 100644 --- a/python/ql/src/Metrics/Internal/ClassExtents.ql +++ b/python/ql/src/Metrics/Internal/ClassExtents.ql @@ -4,6 +4,7 @@ * @id py/class-extents * @metricType reftype */ + import python import Extents diff --git a/python/ql/src/Metrics/Internal/ClassSourceLinks.ql b/python/ql/src/Metrics/Internal/ClassSourceLinks.ql index 089596a0d40..198328f2e8d 100644 --- a/python/ql/src/Metrics/Internal/ClassSourceLinks.ql +++ b/python/ql/src/Metrics/Internal/ClassSourceLinks.ql @@ -4,6 +4,7 @@ * @id py/class-source-links * @metricType reftype */ + import python from Class c diff --git a/python/ql/src/Metrics/Internal/Extents.qll b/python/ql/src/Metrics/Internal/Extents.qll index 283f1fb7c30..9fb12bb244c 100644 --- a/python/ql/src/Metrics/Internal/Extents.qll +++ b/python/ql/src/Metrics/Internal/Extents.qll @@ -15,10 +15,10 @@ import python * including the body (if any), as opposed to the location of its name only. */ class RangeFunction extends Function { - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.getLocation().hasLocationInfo(path, sl, sc, _, _) - and this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) - } + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + super.getLocation().hasLocationInfo(path, sl, sc, _, _) and + this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) + } } /** @@ -26,8 +26,8 @@ class RangeFunction extends Function { * including the body (if any), as opposed to the location of its name only. */ class RangeClass extends Class { - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.getLocation().hasLocationInfo(path, sl, sc, _, _) - and this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) - } -} \ No newline at end of file + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + super.getLocation().hasLocationInfo(path, sl, sc, _, _) and + this.getBody().getLastItem().getLocation().hasLocationInfo(path, _, _, el, ec) + } +} diff --git a/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql b/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql index c950cd4bac4..c0ef582c32b 100644 --- a/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql +++ b/python/ql/src/Metrics/LackofCohesionInMethodsCK.ql @@ -3,14 +3,12 @@ * @description Lack of cohesion in the methods of a class, as defined by Chidamber and Kemerer. * @kind treemap * @id py/lack-of-cohesion-chidamber-kemerer - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType reftype * @metricAggregate avg max */ import python - from ClassMetrics cls -select cls, cls.getLackOfCohesionCK() as n -order by n desc +select cls, cls.getLackOfCohesionCK() as n order by n desc diff --git a/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql b/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql index 0a315c44ea7..5cc77ecfb4f 100644 --- a/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql +++ b/python/ql/src/Metrics/LackofCohesionInMethodsHM.ql @@ -3,14 +3,12 @@ * @description Lack of cohesion of a class, as defined by Hitz and Montazeri. * @kind treemap * @id py/lack-of-cohesion-hitz-montazeri - * @treemap.warnOn highValues + * @treemap.warnOn highValues * @metricType reftype * @metricAggregate avg max */ import python - from ClassMetrics cls -select cls, cls.getLackOfCohesionHM() as n -order by n desc +select cls, cls.getLackOfCohesionHM() as n order by n desc diff --git a/python/ql/src/Metrics/ModuleAfferentCoupling.ql b/python/ql/src/Metrics/ModuleAfferentCoupling.ql index f8f5e0c4208..7bf51433785 100644 --- a/python/ql/src/Metrics/ModuleAfferentCoupling.ql +++ b/python/ql/src/Metrics/ModuleAfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ModuleMetrics m -select m, m.getAfferentCoupling() as n -order by n desc - +select m, m.getAfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/ModuleEfferentCoupling.ql b/python/ql/src/Metrics/ModuleEfferentCoupling.ql index be32b8bc561..51fdcf5423b 100644 --- a/python/ql/src/Metrics/ModuleEfferentCoupling.ql +++ b/python/ql/src/Metrics/ModuleEfferentCoupling.ql @@ -13,6 +13,4 @@ import python from ModuleMetrics m -select m, m.getEfferentCoupling() as n -order by n desc - +select m, m.getEfferentCoupling() as n order by n desc diff --git a/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql b/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql index 4ddd2ba1f0e..00a4c1bf0db 100644 --- a/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql +++ b/python/ql/src/Metrics/NumberOfParametersWithoutDefault.ql @@ -12,7 +12,5 @@ import python - from FunctionMetrics func -select func, func.getNumberOfParametersWithoutDefault() as n -order by n desc +select func, func.getNumberOfParametersWithoutDefault() as n order by n desc diff --git a/python/ql/src/Metrics/NumberOfStatements.ql b/python/ql/src/Metrics/NumberOfStatements.ql index 66263f68a84..a5025d8b95d 100644 --- a/python/ql/src/Metrics/NumberOfStatements.ql +++ b/python/ql/src/Metrics/NumberOfStatements.ql @@ -7,9 +7,9 @@ * @metricType file * @metricAggregate avg sum max */ + import python from Module m, int n where n = count(Stmt s | s.getEnclosingModule() = m) -select m, n -order by n desc +select m, n order by n desc diff --git a/python/ql/src/Metrics/TransitiveImports.ql b/python/ql/src/Metrics/TransitiveImports.ql index cea731388f9..a46a7a16302 100644 --- a/python/ql/src/Metrics/TransitiveImports.ql +++ b/python/ql/src/Metrics/TransitiveImports.ql @@ -9,6 +9,7 @@ * @metricAggregate avg max * @tags modularity */ + import python from ModuleValue m, int n diff --git a/python/ql/src/Numerics/Pythagorean.ql b/python/ql/src/Numerics/Pythagorean.ql index 920ec3f326b..6522da8a2b2 100644 --- a/python/ql/src/Numerics/Pythagorean.ql +++ b/python/ql/src/Numerics/Pythagorean.ql @@ -12,37 +12,34 @@ import python predicate squareOp(BinaryExpr e) { - e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2" + e.getOp() instanceof Pow and e.getRight().(IntegerLiteral).getN() = "2" } predicate squareMul(BinaryExpr e) { - e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId() + e.getOp() instanceof Mult and e.getRight().(Name).getId() = e.getLeft().(Name).getId() } predicate squareRef(Name e) { - e.isUse() and - exists(SsaVariable v, Expr s | - v.getVariable() = e.getVariable() | - s = v.getDefinition().getNode().getParentNode().(AssignStmt).getValue() and - square(s) - ) + e.isUse() and + exists(SsaVariable v, Expr s | v.getVariable() = e.getVariable() | + s = v.getDefinition().getNode().getParentNode().(AssignStmt).getValue() and + square(s) + ) } predicate square(Expr e) { - squareOp(e) - or - squareMul(e) - or - squareRef(e) + squareOp(e) + or + squareMul(e) + or + squareRef(e) } -from - Call c, - BinaryExpr s +from Call c, BinaryExpr s where - c.getFunc().toString() = "sqrt" and - c.getArg(0) = s and - s.getOp() instanceof Add and - square(s.getLeft()) and square(s.getRight()) -select - c, "Pythagorean calculation with sub-optimal numerics" \ No newline at end of file + c.getFunc().toString() = "sqrt" and + c.getArg(0) = s and + s.getOp() instanceof Add and + square(s.getLeft()) and + square(s.getRight()) +select c, "Pythagorean calculation with sub-optimal numerics" diff --git a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql index 59c7d804b5d..3fb7046f8cc 100644 --- a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql +++ b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql @@ -21,7 +21,8 @@ private string commonTopLevelDomainRegex() { result = "com|org|edu|gov|uk|net|io */ bindingset[pattern] predicate isIncompleteHostNameRegExpPattern(string pattern, string hostPart) { - hostPart = pattern + hostPart = + pattern .regexpCapture("(?i).*" + // an unescaped single `.` "(? -
  • Semmle Tutorial: Basic project creation (Python).
  • +
  • Semmle Tutorial: Creating a CodeQL database.
  • diff --git a/python/ql/src/analysis/ImportFailure.ql b/python/ql/src/analysis/ImportFailure.ql index c50b5c6e18c..9c944f9ae83 100644 --- a/python/ql/src/analysis/ImportFailure.ql +++ b/python/ql/src/analysis/ImportFailure.ql @@ -10,14 +10,15 @@ import python ImportExpr alternative_import(ImportExpr ie) { exists(Alias thisalias, Alias otheralias | - (thisalias.getValue() = ie or ((ImportMember)thisalias.getValue()).getModule() = ie) - and - (otheralias.getValue() = result or ((ImportMember)otheralias.getValue()).getModule() = result) - and + (thisalias.getValue() = ie or thisalias.getValue().(ImportMember).getModule() = ie) and + (otheralias.getValue() = result or otheralias.getValue().(ImportMember).getModule() = result) and ( - exists(If i | i.getBody().contains(ie) and i.getOrelse().contains(result)) or - exists(If i | i.getBody().contains(result) and i.getOrelse().contains(ie)) or - exists(Try t | t.getBody().contains(ie) and t.getAHandler().contains(result)) or + exists(If i | i.getBody().contains(ie) and i.getOrelse().contains(result)) + or + exists(If i | i.getBody().contains(result) and i.getOrelse().contains(ie)) + or + exists(Try t | t.getBody().contains(ie) and t.getAHandler().contains(result)) + or exists(Try t | t.getBody().contains(result) and t.getAHandler().contains(ie)) ) ) @@ -31,63 +32,52 @@ string os_specific_import(ImportExpr ie) { or name.matches("Carbon.%") and result = "darwin" or - result = "win32" and ( - name = "_winapi" or name = "_win32api" or name = "_winreg" or - name = "nt" or name.matches("win32%") or name = "ntpath" + result = "win32" and + ( + name = "_winapi" or + name = "_win32api" or + name = "_winreg" or + name = "nt" or + name.matches("win32%") or + name = "ntpath" ) or - result = "linux2" and ( - name = "posix" or name = "posixpath" - ) + result = "linux2" and + (name = "posix" or name = "posixpath") or - result = "unsupported" and ( - name = "__pypy__" or name = "ce" or name.matches("riscos%") - - ) + result = "unsupported" and + (name = "__pypy__" or name = "ce" or name.matches("riscos%")) ) } -string get_os() { - py_flags_versioned("sys.platform", result, major_version().toString()) -} +string get_os() { py_flags_versioned("sys.platform", result, major_version().toString()) } predicate ok_to_fail(ImportExpr ie) { - alternative_import(ie).refersTo(_) - or - os_specific_import(ie) != get_os() + alternative_import(ie).refersTo(_) + or + os_specific_import(ie) != get_os() } - class VersionTest extends @py_flow_node { - - VersionTest() { + VersionTest() { exists(string name | name.matches("%version%") and this.(CompareNode).getAChild+().pointsTo(Module::named("sys").attr(name)) ) } - string toString() { - result = "VersionTest" - } - + string toString() { result = "VersionTest" } } /** A guard on the version of the Python interpreter */ class VersionGuard extends ConditionBlock { - - VersionGuard() { - this.getLastNode() instanceof VersionTest - } - + VersionGuard() { this.getLastNode() instanceof VersionTest } } from ImportExpr ie -where not ie.refersTo(_) and - exists(Context c | c.appliesTo(ie.getAFlowNode())) and - not ok_to_fail(ie) and - not exists(VersionGuard guard | - guard.controls(ie.getAFlowNode().getBasicBlock(), _) - ) - +where + not ie.refersTo(_) and + exists(Context c | c.appliesTo(ie.getAFlowNode())) and + not ok_to_fail(ie) and + not exists(VersionGuard guard | guard.controls(ie.getAFlowNode().getBasicBlock(), _)) select ie, "Unable to resolve import of '" + ie.getImportedModuleName() + "'." diff --git a/python/ql/src/analysis/KeyPointsToFailure.ql b/python/ql/src/analysis/KeyPointsToFailure.ql index 90bc77aa0d7..6cff87dbe85 100644 --- a/python/ql/src/analysis/KeyPointsToFailure.ql +++ b/python/ql/src/analysis/KeyPointsToFailure.ql @@ -11,20 +11,15 @@ import python import semmle.python.pointsto.PointsTo predicate points_to_failure(Expr e) { - exists(ControlFlowNode f | - f = e.getAFlowNode() | - not PointsTo::pointsTo(f, _, _, _) - ) + exists(ControlFlowNode f | f = e.getAFlowNode() | not PointsTo::pointsTo(f, _, _, _)) } predicate key_points_to_failure(Expr e) { - points_to_failure(e) and not points_to_failure(e.getASubExpression()) - and - not exists(SsaVariable ssa | - ssa.getAUse() = e.getAFlowNode() | + points_to_failure(e) and + not points_to_failure(e.getASubExpression()) and + not exists(SsaVariable ssa | ssa.getAUse() = e.getAFlowNode() | points_to_failure(ssa.getAnUltimateDefinition().getDefinition().getNode()) - ) - and + ) and not exists(Assign a | a.getATarget() = e) } diff --git a/python/ql/src/analysis/PointsToFailure.ql b/python/ql/src/analysis/PointsToFailure.ql index 5978e60f513..66ff2d811a3 100644 --- a/python/ql/src/analysis/PointsToFailure.ql +++ b/python/ql/src/analysis/PointsToFailure.ql @@ -11,9 +11,5 @@ import python from Expr e -where exists(ControlFlowNode f | - f = e.getAFlowNode() | - not f.refersTo(_) -) - -select e, "Expression does not 'point-to' any object." \ No newline at end of file +where exists(ControlFlowNode f | f = e.getAFlowNode() | not f.refersTo(_)) +select e, "Expression does not 'point-to' any object." diff --git a/python/ql/src/analysis/Pruned.ql b/python/ql/src/analysis/Pruned.ql index d94bef177ab..f1f43ac3eb3 100644 --- a/python/ql/src/analysis/Pruned.ql +++ b/python/ql/src/analysis/Pruned.ql @@ -1,13 +1,6 @@ - import python import semmle.python.pointsto.PointsTo from int size - -where -size = count(ControlFlowNode f | - not PointsToInternal::reachableBlock(f.getBasicBlock(), _) -) - - +where size = count(ControlFlowNode f | not PointsToInternal::reachableBlock(f.getBasicBlock(), _)) select size diff --git a/python/ql/src/analysis/RatioOfDefinitions.ql b/python/ql/src/analysis/RatioOfDefinitions.ql index 66e0683eab2..13bad7112b9 100644 --- a/python/ql/src/analysis/RatioOfDefinitions.ql +++ b/python/ql/src/analysis/RatioOfDefinitions.ql @@ -3,25 +3,24 @@ */ import python - import DefinitionTracking predicate want_to_have_definition(Expr e) { - /* not builtin object like len, tuple, etc. */ + /* not builtin object like len, tuple, etc. */ not exists(Object cobj | e.refersTo(cobj) and cobj.isC()) and ( e instanceof Name and e.(Name).getCtx() instanceof Load or e instanceof Attribute and e.(Attribute).getCtx() instanceof Load - or - e instanceof ImportMember or + or + e instanceof ImportMember + or e instanceof ImportExpr ) } from int yes, int no -where -yes = count(Expr e | want_to_have_definition(e) and exists(getUniqueDefinition(e))) -and -no = count(Expr e | want_to_have_definition(e) and not exists(getUniqueDefinition(e))) -select yes, no, yes*100/(yes+no) + "%" +where + yes = count(Expr e | want_to_have_definition(e) and exists(getUniqueDefinition(e))) and + no = count(Expr e | want_to_have_definition(e) and not exists(getUniqueDefinition(e))) +select yes, no, yes * 100 / (yes + no) + "%" diff --git a/python/ql/src/analysis/Sanity.ql b/python/ql/src/analysis/Sanity.ql index fc1fa1ab7ad..e34c19099f0 100644 --- a/python/ql/src/analysis/Sanity.ql +++ b/python/ql/src/analysis/Sanity.ql @@ -9,34 +9,44 @@ import DefinitionTracking predicate uniqueness_error(int number, string what, string problem) { ( - what = "toString" or what = "getLocation" or what = "getNode" or what = "getDefinition" or - what = "getEntryNode" or what = "getOrigin" or what = "getAnInferredType" - ) - and + what = "toString" or + what = "getLocation" or + what = "getNode" or + what = "getDefinition" or + what = "getEntryNode" or + what = "getOrigin" or + what = "getAnInferredType" + ) and ( number = 0 and problem = "no results for " + what + "()" or - number in [2 .. 10] and problem = number.toString() + " results for " + what + "()" + number in [2 .. 10] and problem = number.toString() + " results for " + what + "()" ) } predicate ast_sanity(string clsname, string problem, string what) { - exists(AstNode a | - clsname = a.getAQlClass() | - uniqueness_error(count(a.toString()), "toString", problem) and what = "at " + a.getLocation().toString() or - uniqueness_error(strictcount(a.getLocation()), "getLocation", problem) and what = a.getLocation().toString() or - not exists(a.getLocation()) and not a.(Module).isPackage() and problem = "no location" and what = a.toString() + exists(AstNode a | clsname = a.getAQlClass() | + uniqueness_error(count(a.toString()), "toString", problem) and + what = "at " + a.getLocation().toString() + or + uniqueness_error(strictcount(a.getLocation()), "getLocation", problem) and + what = a.getLocation().toString() + or + not exists(a.getLocation()) and + not a.(Module).isPackage() and + problem = "no location" and + what = a.toString() ) } predicate location_sanity(string clsname, string problem, string what) { - exists(Location l | - clsname = l.getAQlClass() | - uniqueness_error(count(l.toString()), "toString", problem) and what = "at " + l.toString() or - not exists(l.toString()) and problem = "no toString" and + exists(Location l | clsname = l.getAQlClass() | + uniqueness_error(count(l.toString()), "toString", problem) and what = "at " + l.toString() + or + not exists(l.toString()) and + problem = "no toString" and ( - exists(AstNode thing | - thing.getLocation() = l | + exists(AstNode thing | thing.getLocation() = l | what = "a location of a " + thing.getAQlClass() ) or @@ -44,32 +54,47 @@ predicate location_sanity(string clsname, string problem, string what) { what = "a location" ) or - l.getEndLine() < l.getStartLine() and problem = "end line before start line" and what = "at " + l.toString() + l.getEndLine() < l.getStartLine() and + problem = "end line before start line" and + what = "at " + l.toString() or - l.getEndLine() = l.getStartLine() and l.getEndColumn() < l.getStartColumn() and - problem = "end column before start column" and what = "at " + l.toString() + l.getEndLine() = l.getStartLine() and + l.getEndColumn() < l.getStartColumn() and + problem = "end column before start column" and + what = "at " + l.toString() ) } predicate cfg_sanity(string clsname, string problem, string what) { - exists(ControlFlowNode f | - clsname = f.getAQlClass() | - uniqueness_error(count(f.getNode()), "getNode", problem) and what = "at " + f.getLocation().toString() + exists(ControlFlowNode f | clsname = f.getAQlClass() | + uniqueness_error(count(f.getNode()), "getNode", problem) and + what = "at " + f.getLocation().toString() or - not exists(f.getLocation()) and not exists(Module p | p.isPackage() | p.getEntryNode() = f or p.getAnExitNode() = f) - and problem = "no location" and what = f.toString() + not exists(f.getLocation()) and + not exists(Module p | p.isPackage() | p.getEntryNode() = f or p.getAnExitNode() = f) and + problem = "no location" and + what = f.toString() or - uniqueness_error(count(f.(AttrNode).getObject()), "getValue", problem) and what = "at " + f.getLocation().toString() + uniqueness_error(count(f.(AttrNode).getObject()), "getValue", problem) and + what = "at " + f.getLocation().toString() ) } predicate scope_sanity(string clsname, string problem, string what) { - exists(Scope s | - clsname = s.getAQlClass() | - uniqueness_error(count(s.getEntryNode()), "getEntryNode", problem) and what = "at " + s.getLocation().toString() or - uniqueness_error(count(s.toString()), "toString", problem) and what = "at " + s.getLocation().toString() or - uniqueness_error(strictcount(s.getLocation()), "getLocation", problem) and what = "at " + s.getLocation().toString() or - not exists(s.getLocation()) and problem = "no location" and what = s.toString() and not s.(Module).isPackage() + exists(Scope s | clsname = s.getAQlClass() | + uniqueness_error(count(s.getEntryNode()), "getEntryNode", problem) and + what = "at " + s.getLocation().toString() + or + uniqueness_error(count(s.toString()), "toString", problem) and + what = "at " + s.getLocation().toString() + or + uniqueness_error(strictcount(s.getLocation()), "getLocation", problem) and + what = "at " + s.getLocation().toString() + or + not exists(s.getLocation()) and + problem = "no location" and + what = s.toString() and + not s.(Module).isPackage() ) } @@ -80,41 +105,57 @@ string best_description_builtin_object(Object o) { or not exists(o.toString()) and py_cobjectnames(o, result) or - not exists(o.toString()) and not py_cobjectnames(o, _) and result = "builtin object of type " + o.getAnInferredType().toString() + not exists(o.toString()) and + not py_cobjectnames(o, _) and + result = "builtin object of type " + o.getAnInferredType().toString() or - not exists(o.toString()) and not py_cobjectnames(o, _) and not exists(o.getAnInferredType().toString()) and result = "builtin object" + not exists(o.toString()) and + not py_cobjectnames(o, _) and + not exists(o.getAnInferredType().toString()) and + result = "builtin object" ) } private predicate introspected_builtin_object(Object o) { - /* Only check objects from the extractor, missing data for objects generated from C source code analysis is OK. - * as it will be ignored if it doesn't match up with the introspected form. */ + /* + * Only check objects from the extractor, missing data for objects generated from C source code analysis is OK. + * as it will be ignored if it doesn't match up with the introspected form. + */ + py_cobject_sources(o, 0) } predicate builtin_object_sanity(string clsname, string problem, string what) { exists(Object o | - clsname = o.getAQlClass() and what = best_description_builtin_object(o) and introspected_builtin_object(o) | - not exists(o.getAnInferredType()) and not py_cobjectnames(o, _) and problem = "neither name nor type" + clsname = o.getAQlClass() and + what = best_description_builtin_object(o) and + introspected_builtin_object(o) + | + not exists(o.getAnInferredType()) and + not py_cobjectnames(o, _) and + problem = "neither name nor type" or uniqueness_error(count(string name | py_cobjectnames(o, name)), "name", problem) or not exists(o.getAnInferredType()) and problem = "no results for getAnInferredType" or - not exists(o.toString()) and problem = "no toString" and + not exists(o.toString()) and + problem = "no toString" and not exists(string name | name.prefix(7) = "_semmle" | py_special_objects(o, name)) and not o = unknownValue() ) } predicate source_object_sanity(string clsname, string problem, string what) { - exists(Object o | - clsname = o.getAQlClass() and not o.isBuiltin() | - uniqueness_error(count(o.getOrigin()), "getOrigin", problem) and what = "at " + o.getOrigin().getLocation().toString() + exists(Object o | clsname = o.getAQlClass() and not o.isBuiltin() | + uniqueness_error(count(o.getOrigin()), "getOrigin", problem) and + what = "at " + o.getOrigin().getLocation().toString() or not exists(o.getOrigin().getLocation()) and problem = "no location" and what = "??" or - not exists(o.toString()) and problem = "no toString" and what = "at " + o.getOrigin().getLocation().toString() + not exists(o.toString()) and + problem = "no toString" and + what = "at " + o.getOrigin().getLocation().toString() or strictcount(o.toString()) > 1 and problem = "multiple toStrings()" and what = o.toString() ) @@ -122,55 +163,64 @@ predicate source_object_sanity(string clsname, string problem, string what) { predicate ssa_sanity(string clsname, string problem, string what) { /* Zero or one definitions of each SSA variable */ - exists(SsaVariable var | - clsname = var.getAQlClass() | - uniqueness_error(strictcount(var.getDefinition()), "getDefinition", problem) and what = var.getId() + exists(SsaVariable var | clsname = var.getAQlClass() | + uniqueness_error(strictcount(var.getDefinition()), "getDefinition", problem) and + what = var.getId() ) or /* Dominance criterion: Definition *must* dominate *all* uses. */ exists(SsaVariable var, ControlFlowNode defn, ControlFlowNode use | - defn = var.getDefinition() and use = var.getAUse() | - not defn.strictlyDominates(use) and not defn = use and + defn = var.getDefinition() and use = var.getAUse() + | + not defn.strictlyDominates(use) and + not defn = use and /* Phi nodes which share a flow node with a use come *before* the use */ not (exists(var.getAPhiInput()) and defn = use) and - clsname = var.getAQlClass() and problem = "a definition which does not dominate a use at " + use.getLocation() and what = var.getId() + " at " + var.getLocation() + clsname = var.getAQlClass() and + problem = "a definition which does not dominate a use at " + use.getLocation() and + what = var.getId() + " at " + var.getLocation() ) or /* Minimality of phi nodes */ exists(SsaVariable var | strictcount(var.getAPhiInput()) = 1 and - var.getAPhiInput().getDefinition().getBasicBlock().strictlyDominates(var.getDefinition().getBasicBlock()) - | - clsname = var.getAQlClass() and problem = " a definition which is dominated by the definition of an incoming phi edge." and what = var.getId() + " at " + var.getLocation() + var + .getAPhiInput() + .getDefinition() + .getBasicBlock() + .strictlyDominates(var.getDefinition().getBasicBlock()) + | + clsname = var.getAQlClass() and + problem = " a definition which is dominated by the definition of an incoming phi edge." and + what = var.getId() + " at " + var.getLocation() ) } predicate function_object_sanity(string clsname, string problem, string what) { - exists(FunctionObject func | - clsname = func.getAQlClass() | + exists(FunctionObject func | clsname = func.getAQlClass() | what = func.getName() and ( count(func.descriptiveString()) = 0 and problem = "no descriptiveString()" or - exists(int c | - c = strictcount(func.descriptiveString()) and c > 1 | + exists(int c | c = strictcount(func.descriptiveString()) and c > 1 | problem = c + "descriptiveString()s" ) ) - or + or not exists(func.getName()) and what = "?" and problem = "no name" ) - } predicate multiple_origins_per_object(Object obj) { - not obj.isC() and not obj instanceof ModuleObject and - exists(ControlFlowNode use, Context ctx | strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1) + not obj.isC() and + not obj instanceof ModuleObject and + exists(ControlFlowNode use, Context ctx | + strictcount(ControlFlowNode orig | use.refersTo(ctx, obj, _, orig)) > 1 + ) } predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Object obj) { - exists(ControlFlowNode orig, Context ctx | - not inter = orig | + exists(ControlFlowNode orig, Context ctx | not inter = orig | use.refersTo(ctx, obj, _, inter) and inter.refersTo(ctx, obj, _, orig) and // It can sometimes happen that two different modules (e.g. cPickle and Pickle) @@ -181,8 +231,10 @@ predicate intermediate_origins(ControlFlowNode use, ControlFlowNode inter, Objec predicate points_to_sanity(string clsname, string problem, string what) { exists(Object obj | - multiple_origins_per_object(obj) and clsname = obj.getAQlClass() and - problem = "multiple origins for an object" and what = obj.toString() + multiple_origins_per_object(obj) and + clsname = obj.getAQlClass() and + problem = "multiple origins for an object" and + what = obj.toString() ) or exists(ControlFlowNode use, ControlFlowNode inter, Object obj | @@ -194,8 +246,8 @@ predicate points_to_sanity(string clsname, string problem, string what) { } predicate jump_to_definition_sanity(string clsname, string problem, string what) { - problem = "multiple (jump-to) definitions" and - exists(Expr use | + problem = "multiple (jump-to) definitions" and + exists(Expr use | strictcount(getUniqueDefinition(use)) > 1 and clsname = use.getAQlClass() and what = use.toString() @@ -208,10 +260,12 @@ predicate file_sanity(string clsname, string problem, string what) { problem = "has same name as a folder" and what = file.getAbsolutePath() and what = folder.getAbsolutePath() - ) or + ) + or exists(Container f | clsname = f.getAQlClass() and - uniqueness_error(count(f.toString()), "toString", problem) and what = "file " + f.getName() + uniqueness_error(count(f.toString()), "toString", problem) and + what = "file " + f.getName() ) } @@ -228,17 +282,17 @@ predicate class_value_sanity(string clsname, string problem, string what) { } from string clsname, string problem, string what -where -ast_sanity(clsname, problem, what) or -location_sanity(clsname, problem, what)or -scope_sanity(clsname, problem, what) or -cfg_sanity(clsname, problem, what) or -ssa_sanity(clsname, problem, what) or -builtin_object_sanity(clsname, problem, what) or -source_object_sanity(clsname, problem, what) or -function_object_sanity(clsname, problem, what) or -points_to_sanity(clsname, problem, what) or -jump_to_definition_sanity(clsname, problem, what) or -file_sanity(clsname, problem, what) or -class_value_sanity(clsname, problem, what) +where + ast_sanity(clsname, problem, what) or + location_sanity(clsname, problem, what) or + scope_sanity(clsname, problem, what) or + cfg_sanity(clsname, problem, what) or + ssa_sanity(clsname, problem, what) or + builtin_object_sanity(clsname, problem, what) or + source_object_sanity(clsname, problem, what) or + function_object_sanity(clsname, problem, what) or + points_to_sanity(clsname, problem, what) or + jump_to_definition_sanity(clsname, problem, what) or + file_sanity(clsname, problem, what) or + class_value_sanity(clsname, problem, what) select clsname + " " + what + " has " + problem diff --git a/python/ql/src/analysis/Summary.ql b/python/ql/src/analysis/Summary.ql index ba2fee0b4a8..55564edb16e 100644 --- a/python/ql/src/analysis/Summary.ql +++ b/python/ql/src/analysis/Summary.ql @@ -1,38 +1,43 @@ -/** Summarize a snapshot +/** + * Summarize a snapshot */ import python from string key, string value where -key = "Extractor version" and py_flags_versioned("extractor.version", value, _) -or -key = "Snapshot build time" and exists(date d | snapshotDate(d) and value = d.toString()) -or -key = "Interpreter version" and -exists(string major, string minor | - py_flags_versioned("version.major", major, _) and - py_flags_versioned("version.minor", minor, _) and - value = major + "." + minor -) -or -key = "Build platform" and -exists(string raw | - py_flags_versioned("sys.platform", raw, _) | - if raw = "win32" then - value = "Windows" - else if raw = "linux2" then - value = "Linux" - else if raw = "darwin" then - value = "OSX" - else - value = raw -) -or -key = "Source location" and sourceLocationPrefix(value) -or -key = "Lines of code (source)" and value = sum(ModuleMetrics m | exists(m.getFile().getRelativePath()) | m.getNumberOfLinesOfCode()).toString() -or -key = "Lines of code (total)" and value = sum(ModuleMetrics m | any() | m.getNumberOfLinesOfCode()).toString() - + key = "Extractor version" and py_flags_versioned("extractor.version", value, _) + or + key = "Snapshot build time" and + exists(date d | snapshotDate(d) and value = d.toString()) + or + key = "Interpreter version" and + exists(string major, string minor | + py_flags_versioned("version.major", major, _) and + py_flags_versioned("version.minor", minor, _) and + value = major + "." + minor + ) + or + key = "Build platform" and + exists(string raw | py_flags_versioned("sys.platform", raw, _) | + if raw = "win32" + then value = "Windows" + else + if raw = "linux2" + then value = "Linux" + else + if raw = "darwin" + then value = "OSX" + else value = raw + ) + or + key = "Source location" and sourceLocationPrefix(value) + or + key = "Lines of code (source)" and + value = + sum(ModuleMetrics m | exists(m.getFile().getRelativePath()) | m.getNumberOfLinesOfCode()) + .toString() + or + key = "Lines of code (total)" and + value = sum(ModuleMetrics m | any() | m.getNumberOfLinesOfCode()).toString() select key, value diff --git a/python/ql/src/analysis/TypeHierarchyFailure.ql b/python/ql/src/analysis/TypeHierarchyFailure.ql index 8aac3ea236b..c4c91005743 100644 --- a/python/ql/src/analysis/TypeHierarchyFailure.ql +++ b/python/ql/src/analysis/TypeHierarchyFailure.ql @@ -9,8 +9,6 @@ import python - from Class cls, string reason -where -exists(ClassObject c | c.getPyClass() = cls | c.failedInference(reason)) +where exists(ClassObject c | c.getPyClass() = cls | c.failedInference(reason)) select cls, "Inference of class hierarchy failed for class '" + cls.getName() + "': " + reason + "." diff --git a/python/ql/src/analysis/TypeInferenceFailure.ql b/python/ql/src/analysis/TypeInferenceFailure.ql index 1b8237d65a1..0e6e42e8385 100644 --- a/python/ql/src/analysis/TypeInferenceFailure.ql +++ b/python/ql/src/analysis/TypeInferenceFailure.ql @@ -6,10 +6,11 @@ * @id py/type-inference-failure * @deprecated */ + import python - from ControlFlowNode f, Object o -where f.refersTo(o) and -not exists(ClassObject c | f.refersTo(o, c, _)) -select o, "Type inference fails for 'object'." \ No newline at end of file +where + f.refersTo(o) and + not exists(ClassObject c | f.refersTo(o, c, _)) +select o, "Type inference fails for 'object'." diff --git a/python/ql/src/codeql-suites/python-code-scanning.qls b/python/ql/src/codeql-suites/python-code-scanning.qls new file mode 100644 index 00000000000..f9f9a5425b6 --- /dev/null +++ b/python/ql/src/codeql-suites/python-code-scanning.qls @@ -0,0 +1,4 @@ +- description: Standard Code Scanning queries for Python +- qlpack: codeql-python +- apply: code-scanning-selectors.yml + from: codeql-suite-helpers diff --git a/python/ql/src/default.qll b/python/ql/src/default.qll index 99374e13f76..8fa398db399 100644 --- a/python/ql/src/default.qll +++ b/python/ql/src/default.qll @@ -2,4 +2,5 @@ * WARNING: Use of this module is DEPRECATED. * All new queries should use `import python`. */ + import python diff --git a/python/ql/src/external/CodeDuplication.qll b/python/ql/src/external/CodeDuplication.qll index 3178f8d463a..d558ee7e8a7 100644 --- a/python/ql/src/external/CodeDuplication.qll +++ b/python/ql/src/external/CodeDuplication.qll @@ -3,10 +3,7 @@ import python /** Gets the relative path of `file`, with backslashes replaced by forward slashes. */ -private -string relativePath(File file) { - result = file.getRelativePath().replaceAll("\\", "/") -} +private string relativePath(File file) { result = file.getRelativePath().replaceAll("\\", "/") } /** * Holds if the `index`-th token of block `copy` is in file `file`, spanning @@ -21,60 +18,42 @@ private predicate tokenLocation(File file, int sl, int sc, int ec, int el, Copy } /** A token block used for detection of duplicate and similar code. */ -class Copy extends @duplication_or_similarity -{ - private - int lastToken() { - result = max(int i | tokens(this, i, _, _, _, _) | i) - } +class Copy extends @duplication_or_similarity { + private int lastToken() { result = max(int i | tokens(this, i, _, _, _, _) | i) } /** Gets the index of the token in this block starting at the location `loc`, if any. */ int tokenStartingAt(Location loc) { - tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), - _, _, this, result) + tokenLocation(loc.getFile(), loc.getStartLine(), loc.getStartColumn(), _, _, this, result) } /** Gets the index of the token in this block ending at the location `loc`, if any. */ int tokenEndingAt(Location loc) { - tokenLocation(loc.getFile(), _, _, - loc.getEndLine(), loc.getEndColumn(), this, result) + tokenLocation(loc.getFile(), _, _, loc.getEndLine(), loc.getEndColumn(), this, result) } /** Gets the line on which the first token in this block starts. */ - int sourceStartLine() { - tokens(this, 0, result, _, _, _) - } + int sourceStartLine() { tokens(this, 0, result, _, _, _) } /** Gets the column on which the first token in this block starts. */ - int sourceStartColumn() { - tokens(this, 0, _, result, _, _) - } + int sourceStartColumn() { tokens(this, 0, _, result, _, _) } /** Gets the line on which the last token in this block ends. */ - int sourceEndLine() { - tokens(this, this.lastToken(), _, _, result, _) - } + int sourceEndLine() { tokens(this, this.lastToken(), _, _, result, _) } /** Gets the column on which the last token in this block ends. */ - int sourceEndColumn() { - tokens(this, this.lastToken(), _, _, _, result) - } + int sourceEndColumn() { tokens(this, this.lastToken(), _, _, _, result) } /** Gets the number of lines containing at least (part of) one token in this block. */ - int sourceLines() { - result = this.sourceEndLine() + 1 - this.sourceStartLine() - } + int sourceLines() { result = this.sourceEndLine() + 1 - this.sourceStartLine() } /** Gets an opaque identifier for the equivalence class of this block. */ - int getEquivalenceClass() { - duplicateCode(this, _, result) or similarCode(this, _, result) - } + int getEquivalenceClass() { duplicateCode(this, _, result) or similarCode(this, _, result) } /** Gets the source file in which this block appears. */ File sourceFile() { - exists(string name | - duplicateCode(this, name, _) or similarCode(this, name, _) | - name.replaceAll("\\", "/") = relativePath(result)) + exists(string name | duplicateCode(this, name, _) or similarCode(this, name, _) | + name.replaceAll("\\", "/") = relativePath(result) + ) } /** @@ -84,8 +63,10 @@ class Copy extends @duplication_or_similarity * For more information, see * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ - predicate hasLocationInfo(string filepath, int startline, int startcolumn, int endline, int endcolumn) { - sourceFile().getName() = filepath and + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + sourceFile().getAbsolutePath() = filepath and startline = sourceStartLine() and startcolumn = sourceStartColumn() and endline = sourceEndLine() and @@ -102,7 +83,8 @@ class Copy extends @duplication_or_similarity Copy extendingBlock() { exists(File file, int sl, int sc, int ec, int el | tokenLocation(file, sl, sc, ec, el, this, _) and - tokenLocation(file, sl, sc, ec, el, result, 0)) and + tokenLocation(file, sl, sc, ec, el, result, 0) + ) and this != result } } @@ -113,13 +95,17 @@ class Copy extends @duplication_or_similarity * have the same equivalence class, with `start` being the equivalence class of `start1` and * `start2`, and `end` the equivalence class of `end1` and `end2`. */ -predicate similar_extension(SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext) { +predicate similar_extension( + SimilarBlock start1, SimilarBlock start2, SimilarBlock ext1, SimilarBlock ext2, int start, int ext +) { start1.getEquivalenceClass() = start and start2.getEquivalenceClass() = start and ext1.getEquivalenceClass() = ext and ext2.getEquivalenceClass() = ext and start1 != start2 and - (ext1 = start1 and ext2 = start2 or + ( + ext1 = start1 and ext2 = start2 + or similar_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext) ) } @@ -130,28 +116,29 @@ predicate similar_extension(SimilarBlock start1, SimilarBlock start2, SimilarBlo * have the same equivalence class, with `start` being the equivalence class of `start1` and * `start2`, and `end` the equivalence class of `end1` and `end2`. */ -predicate duplicate_extension(DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start, int ext) { +predicate duplicate_extension( + DuplicateBlock start1, DuplicateBlock start2, DuplicateBlock ext1, DuplicateBlock ext2, int start, + int ext +) { start1.getEquivalenceClass() = start and start2.getEquivalenceClass() = start and ext1.getEquivalenceClass() = ext and ext2.getEquivalenceClass() = ext and start1 != start2 and - (ext1 = start1 and ext2 = start2 or + ( + ext1 = start1 and ext2 = start2 + or duplicate_extension(start1.extendingBlock(), start2.extendingBlock(), ext1, ext2, _, ext) ) } /** A block of duplicated code. */ -class DuplicateBlock extends Copy, @duplication -{ - override string toString() { - result = "Duplicate code: " + sourceLines() + " duplicated lines." - } +class DuplicateBlock extends Copy, @duplication { + override string toString() { result = "Duplicate code: " + sourceLines() + " duplicated lines." } } /** A block of similar code. */ -class SimilarBlock extends Copy, @similarity -{ +class SimilarBlock extends Copy, @similarity { override string toString() { result = "Similar code: " + sourceLines() + " almost duplicated lines." } @@ -167,8 +154,9 @@ predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) scope2.contains(stmt2) and duplicateCoversStatement(equivstart, equivend, first, last, stmt1) and duplicateCoversStatement(equivstart, equivend, first, last, stmt2) and - stmt1 != stmt2 and scope1 != scope2 - ) + stmt1 != stmt2 and + scope1 != scope2 + ) } /** @@ -178,8 +166,9 @@ predicate duplicateStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) * and `equivstart` and `equivend` are the equivalence classes of the first and the last * block, respectively. */ -private -predicate duplicateCoversStatement(int equivstart, int equivend, int first, int last, Stmt stmt) { +private predicate duplicateCoversStatement( + int equivstart, int equivend, int first, int last, Stmt stmt +) { exists(DuplicateBlock b1, DuplicateBlock b2, Location startloc, Location endloc | stmt.getLocation() = startloc and stmt.getLastStatement().getLocation() = endloc and @@ -204,13 +193,14 @@ predicate duplicateStatements(Scope scope1, Scope scope2, int duplicate, int tot * Find pairs of scopes that are identical or almost identical */ predicate duplicateScopes(Scope s, Scope other, float percent, string message) { - exists(int total, int duplicate | - duplicateStatements(s, other, duplicate, total) | - percent = 100.0 * duplicate / total and percent >= 80.0 and - if duplicate = total then - message = "All " + total + " statements in " + s.getName() + " are identical in $@." + exists(int total, int duplicate | duplicateStatements(s, other, duplicate, total) | + percent = 100.0 * duplicate / total and + percent >= 80.0 and + if duplicate = total + then message = "All " + total + " statements in " + s.getName() + " are identical in $@." else - message = duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@." + message = + duplicate + " out of " + total + " statements in " + s.getName() + " are duplicated in $@." ) } @@ -219,12 +209,13 @@ predicate duplicateScopes(Scope s, Scope other, float percent, string message) { * respectively, where `scope1` and `scope2` are not the same. */ private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt stmt2) { - exists(int start, int end, int first, int last | + exists(int start, int end, int first, int last | scope1.contains(stmt1) and scope2.contains(stmt2) and similarCoversStatement(start, end, first, last, stmt1) and similarCoversStatement(start, end, first, last, stmt2) and - stmt1 != stmt2 and scope1 != scope2 + stmt1 != stmt2 and + scope1 != scope2 ) } @@ -235,7 +226,9 @@ private predicate similarStatement(Scope scope1, Scope scope2, Stmt stmt1, Stmt * and `equivstart` and `equivend` are the equivalence classes of the first and the last * block, respectively. */ -private predicate similarCoversStatement(int equivstart, int equivend, int first, int last, Stmt stmt) { +private predicate similarCoversStatement( + int equivstart, int equivend, int first, int last, Stmt stmt +) { exists(SimilarBlock b1, SimilarBlock b2, Location startloc, Location endloc | stmt.getLocation() = startloc and stmt.getLastStatement().getLocation() = endloc and @@ -260,13 +253,14 @@ private predicate similarStatements(Scope scope1, Scope scope2, int similar, int * Find pairs of scopes that are similar */ predicate similarScopes(Scope s, Scope other, float percent, string message) { - exists(int total, int similar | - similarStatements(s, other, similar, total) | - percent = 100.0 * similar / total and percent >= 80.0 and - if similar = total then - message = "All statements in " + s.getName() + " are similar in $@." + exists(int total, int similar | similarStatements(s, other, similar, total) | + percent = 100.0 * similar / total and + percent >= 80.0 and + if similar = total + then message = "All statements in " + s.getName() + " are similar in $@." else - message = similar + " out of " + total + " statements in " + s.getName() + " are similar in $@." + message = + similar + " out of " + total + " statements in " + s.getName() + " are similar in $@." ) } @@ -275,7 +269,5 @@ predicate similarScopes(Scope s, Scope other, float percent, string message) { * This is true for blocks of import statements. */ predicate whitelistedLineForDuplication(File f, int line) { - exists(ImportingStmt i | - i.getLocation().getFile() = f and i.getLocation().getStartLine() = line - ) + exists(ImportingStmt i | i.getLocation().getFile() = f and i.getLocation().getStartLine() = line) } diff --git a/python/ql/src/external/DefectFilter.qll b/python/ql/src/external/DefectFilter.qll index e34385acfb8..38419dee2ec 100644 --- a/python/ql/src/external/DefectFilter.qll +++ b/python/ql/src/external/DefectFilter.qll @@ -10,58 +10,61 @@ import semmle.python.Files * * For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). */ -external predicate defectResults(int id, string queryPath, string filepath, int startline, - int startcol, int endline, int endcol, string message); +external predicate defectResults( + int id, string queryPath, string filepath, int startline, int startcol, int endline, int endcol, + string message +); /** * A defect query result stored in a dashboard database. */ class DefectResult extends int { + DefectResult() { defectResults(this, _, _, _, _, _, _, _) } - DefectResult() { defectResults(this, _, _, _, _, _, _, _) } + /** Gets the path of the query that reported the result. */ + string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } - /** Gets the path of the query that reported the result. */ - string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) } + /** Gets the file in which this query result was reported. */ + File getFile() { + exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path) + } - /** Gets the file in which this query result was reported. */ - File getFile() { - exists(string path | defectResults(this, _, path, _, _, _, _, _) and result.getName() = path) - } + /** Gets the file path in which this query result was reported. */ + string getFilePath() { defectResults(this, _, result, _, _, _, _, _) } - /** Gets the file path in which this query result was reported. */ - string getFilePath() { defectResults(this, _, result, _, _, _, _, _) } + /** Gets the line on which the location of this query result starts. */ + int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } - /** Gets the line on which the location of this query result starts. */ - int getStartLine() { defectResults(this, _, _, result, _, _, _, _) } + /** Gets the column on which the location of this query result starts. */ + int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } - /** Gets the column on which the location of this query result starts. */ - int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) } + /** Gets the line on which the location of this query result ends. */ + int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } - /** Gets the line on which the location of this query result ends. */ - int getEndLine() { defectResults(this, _, _, _, _, result, _, _) } + /** Gets the column on which the location of this query result ends. */ + int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } - /** Gets the column on which the location of this query result ends. */ - int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) } + /** Gets the message associated with this query result. */ + string getMessage() { defectResults(this, _, _, _, _, _, _, result) } - /** Gets the message associated with this query result. */ - string getMessage() { defectResults(this, _, _, _, _, _, _, result) } - - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - defectResults(this, _, path, sl, sc, el, ec, _) - } - - /** Gets the URL corresponding to the location of this query result. */ - string getURL() { - result = "file://" + getFile().getName() + ":" + getStartLine() + ":" + getStartColumn() + ":" + getEndLine() + ":" + getEndColumn() - } + predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { + defectResults(this, _, path, sl, sc, el, ec, _) + } + /** Gets the URL corresponding to the location of this query result. */ + string getURL() { + result = + "file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" + + getEndLine() + ":" + getEndColumn() + } } // crude containment by line number only predicate contains(Location l, DefectResult res) { - exists(string path, int bl1, int el1, int bl2, int el2 | - l.hasLocationInfo(path, bl1, _, el1, _) - and res.hasLocationInfo(path, bl2, _, el2, _) - and bl1 <= bl2 and el1 >= el2 - ) + exists(string path, int bl1, int el1, int bl2, int el2 | + l.hasLocationInfo(path, bl1, _, el1, _) and + res.hasLocationInfo(path, bl2, _, el2, _) and + bl1 <= bl2 and + el1 >= el2 + ) } diff --git a/python/ql/src/external/DuplicateBlock.ql b/python/ql/src/external/DuplicateBlock.ql index f9a75f437a2..38aed20739f 100644 --- a/python/ql/src/external/DuplicateBlock.ql +++ b/python/ql/src/external/DuplicateBlock.ql @@ -14,21 +14,21 @@ * @precision medium * @id py/duplicate-block */ + import python import CodeDuplication predicate sorted_by_location(DuplicateBlock x, DuplicateBlock y) { - if x.sourceFile() = y.sourceFile() then - x.sourceStartLine() < y.sourceStartLine() - else - x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath() + if x.sourceFile() = y.sourceFile() + then x.sourceStartLine() < y.sourceStartLine() + else x.sourceFile().getAbsolutePath() < y.sourceFile().getAbsolutePath() } from DuplicateBlock d, DuplicateBlock other -where d.sourceLines() > 10 and - other.getEquivalenceClass() = d.getEquivalenceClass() and - sorted_by_location(other, d) -select - d, - "Duplicate code: " + d.sourceLines() + " lines are duplicated at " + - other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString() +where + d.sourceLines() > 10 and + other.getEquivalenceClass() = d.getEquivalenceClass() and + sorted_by_location(other, d) +select d, + "Duplicate code: " + d.sourceLines() + " lines are duplicated at " + + other.sourceFile().getShortName() + ":" + other.sourceStartLine().toString() diff --git a/python/ql/src/external/DuplicateFunction.ql b/python/ql/src/external/DuplicateFunction.ql index ddf587caf68..b638f6fb5b2 100644 --- a/python/ql/src/external/DuplicateFunction.ql +++ b/python/ql/src/external/DuplicateFunction.ql @@ -13,19 +13,17 @@ * @precision high * @id py/duplicate-function */ + import python import CodeDuplication -predicate relevant(Function m) { - m.getMetrics().getNumberOfLinesOfCode() > 5 -} +predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 5 } from Function m, Function other, string message, int percent -where duplicateScopes(m, other, percent, message) - and relevant(m) - and percent > 95.0 - and not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) - and not duplicateScopes(m.getScope(), other.getScope(), _, _) -select m, message, - other, - other.getName() +where + duplicateScopes(m, other, percent, message) and + relevant(m) and + percent > 95.0 and + not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and + not duplicateScopes(m.getScope(), other.getScope(), _, _) +select m, message, other, other.getName() diff --git a/python/ql/src/external/ExternalArtifact.qll b/python/ql/src/external/ExternalArtifact.qll index 9c2fe6a9b66..0ed2c8d4878 100644 --- a/python/ql/src/external/ExternalArtifact.qll +++ b/python/ql/src/external/ExternalArtifact.qll @@ -1,7 +1,6 @@ import python class ExternalDefect extends @externalDefect { - string getQueryPath() { exists(string path | externalDefects(this, path, _, _, _) and @@ -9,95 +8,59 @@ class ExternalDefect extends @externalDefect { ) } - string getMessage() { - externalDefects(this, _, _, result, _) - } + string getMessage() { externalDefects(this, _, _, result, _) } - float getSeverity() { - externalDefects(this, _, _, _, result) - } + float getSeverity() { externalDefects(this, _, _, _, result) } - Location getLocation() { - externalDefects(this,_,result,_,_) - } + Location getLocation() { externalDefects(this, _, result, _, _) } - string toString() { - result = getQueryPath() + ": " + getLocation() + " - " + getMessage() - } + string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getMessage() } } class ExternalMetric extends @externalMetric { + string getQueryPath() { externalMetrics(this, result, _, _) } - string getQueryPath() { - externalMetrics(this, result, _, _) - } + float getValue() { externalMetrics(this, _, _, result) } - float getValue() { - externalMetrics(this, _, _, result) - } + Location getLocation() { externalMetrics(this, _, result, _) } - Location getLocation() { - externalMetrics(this,_,result,_) - } - - string toString() { - result = getQueryPath() + ": " + getLocation() + " - " + getValue() - } + string toString() { result = getQueryPath() + ": " + getLocation() + " - " + getValue() } } class ExternalData extends @externalDataElement { + string getDataPath() { externalData(this, result, _, _) } - string getDataPath() { - externalData(this, result, _, _) - } + string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") } - string getQueryPath() { - result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") - } + int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) } - int getNumFields() { - result = 1 + max(int i | externalData(this, _, i, _) | i) - } + string getField(int index) { externalData(this, _, index, result) } - string getField(int index) { - externalData(this, _, index, result) - } + int getFieldAsInt(int index) { result = getField(index).toInt() } - int getFieldAsInt(int index) { - result = getField(index).toInt() - } + float getFieldAsFloat(int index) { result = getField(index).toFloat() } - float getFieldAsFloat(int index) { - result = getField(index).toFloat() - } + date getFieldAsDate(int index) { result = getField(index).toDate() } - date getFieldAsDate(int index) { - result = getField(index).toDate() - } - - string toString() { - result = getQueryPath() + ": " + buildTupleString(0) - } + string toString() { result = getQueryPath() + ": " + buildTupleString(0) } private string buildTupleString(int start) { - (start = getNumFields() - 1 and result = getField(start)) + start = getNumFields() - 1 and result = getField(start) or - (start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start+1)) + start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1) } - } /** * External data with a location, and a message, as produced by tools that used to produce QLDs. */ class DefectExternalData extends ExternalData { - DefectExternalData() { - this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and - this.getNumFields() = 2 - } - - string getURL() { result = getField(0) } + DefectExternalData() { + this.getField(0).regexpMatch("\\w+://.*:[0-9]+:[0-9]+:[0-9]+:[0-9]+$") and + this.getNumFields() = 2 + } - string getMessage() { result = getField(1) } + string getURL() { result = getField(0) } + + string getMessage() { result = getField(1) } } - diff --git a/python/ql/src/external/MostlyDuplicateClass.ql b/python/ql/src/external/MostlyDuplicateClass.ql index 7a6f0b7587d..88169ab897f 100644 --- a/python/ql/src/external/MostlyDuplicateClass.ql +++ b/python/ql/src/external/MostlyDuplicateClass.ql @@ -13,12 +13,13 @@ * @precision high * @id py/mostly-duplicate-class */ + import python import CodeDuplication from Class c, Class other, string message -where duplicateScopes(c, other, _, message) - and count(c.getAStmt()) > 3 - and not duplicateScopes(c.getEnclosingModule(), _, _, _) +where + duplicateScopes(c, other, _, message) and + count(c.getAStmt()) > 3 and + not duplicateScopes(c.getEnclosingModule(), _, _, _) select c, message, other, other.getName() - diff --git a/python/ql/src/external/MostlyDuplicateFile.ql b/python/ql/src/external/MostlyDuplicateFile.ql index 57178d8846e..78df1a4166e 100644 --- a/python/ql/src/external/MostlyDuplicateFile.ql +++ b/python/ql/src/external/MostlyDuplicateFile.ql @@ -13,6 +13,7 @@ * @precision high * @id py/mostly-duplicate-file */ + import python import CodeDuplication diff --git a/python/ql/src/external/MostlySimilarFile.ql b/python/ql/src/external/MostlySimilarFile.ql index 4bdcce626c9..97413885962 100644 --- a/python/ql/src/external/MostlySimilarFile.ql +++ b/python/ql/src/external/MostlySimilarFile.ql @@ -9,11 +9,11 @@ * duplicate-code * statistical * non-attributable - * @problem.severity recommendation * @sub-severity low * @precision high * @id py/mostly-similar-file */ + import python import CodeDuplication diff --git a/python/ql/src/external/SimilarFunction.ql b/python/ql/src/external/SimilarFunction.ql index 9d0a3f72cfb..bcd63a41dcf 100644 --- a/python/ql/src/external/SimilarFunction.ql +++ b/python/ql/src/external/SimilarFunction.ql @@ -13,23 +13,18 @@ * @precision very-high * @id py/similar-function */ + import python import CodeDuplication -predicate relevant(Function m) { - m.getMetrics().getNumberOfLinesOfCode() > 10 -} +predicate relevant(Function m) { m.getMetrics().getNumberOfLinesOfCode() > 10 } from Function m, Function other, string message, int percent -where similarScopes(m, other, percent, message) and +where + similarScopes(m, other, percent, message) and relevant(m) and percent > 95.0 and not duplicateScopes(m, other, _, _) and not duplicateScopes(m.getEnclosingModule(), other.getEnclosingModule(), _, _) and not duplicateScopes(m.getScope(), other.getScope(), _, _) -select m, message, - other, - other.getName() - - - +select m, message, other, other.getName() diff --git a/python/ql/src/external/Thrift.qll b/python/ql/src/external/Thrift.qll index a10d5aab506..658d3f301cd 100644 --- a/python/ql/src/external/Thrift.qll +++ b/python/ql/src/external/Thrift.qll @@ -3,68 +3,42 @@ * This code is under development and may change without warning. */ - import external.ExternalArtifact /** An item in the parse tree of the IDL file */ class ThriftElement extends ExternalData { - string kind; - ThriftElement() { - this.getDataPath() = "thrift-" + kind - } + ThriftElement() { this.getDataPath() = "thrift-" + kind } - string getKind() { - result = kind - } + string getKind() { result = kind } - string getId() { - result = getField(0) - } + string getId() { result = getField(0) } - int getIndex() { - result = getFieldAsInt(1) - } + int getIndex() { result = getFieldAsInt(1) } - ThriftElement getParent() { - result.getId() = this.getField(2) - } + ThriftElement getParent() { result.getId() = this.getField(2) } - string getValue() { - result = this.getField(3) - } + string getValue() { result = this.getField(3) } - ThriftElement getChild(int n) { - result.getIndex() = n and result.getParent() = this - } + ThriftElement getChild(int n) { result.getIndex() = n and result.getParent() = this } - ThriftElement getAChild() { - result = this.getChild(_) - } + ThriftElement getAChild() { result = this.getChild(_) } - override string toString() { - result = this.getKind() - } + override string toString() { result = this.getKind() } - string getPath() { - result = this.getField(4) - } + string getPath() { result = this.getField(4) } - private int line() { - result = this.getFieldAsInt(5) - } + private int line() { result = this.getFieldAsInt(5) } - private int column() { - result = this.getFieldAsInt(6) - } + private int column() { result = this.getFieldAsInt(6) } predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) { fp = this.getPath() and bl = this.line() and bc = this.column() and el = this.line() and - ec = this.column() + this.getValue().length()-1 + ec = this.column() + this.getValue().length() - 1 or exists(ThriftElement first, ThriftElement last | first = this.getChild(min(int l | exists(this.getChild(l)))) and @@ -74,19 +48,13 @@ class ThriftElement extends ExternalData { ) } - File getFile() { - this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) - } - + File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) } } abstract class ThriftNamedElement extends ThriftElement { - abstract ThriftElement getNameElement(); - final string getName() { - result = this.getNameElement().getValue() - } + final string getName() { result = this.getNameElement().getValue() } override string toString() { result = this.getKind() + " " + this.getName() @@ -101,14 +69,10 @@ abstract class ThriftNamedElement extends ThriftElement { this.getNameElement().hasLocationInfo(fp, _, _, el, ec) ) } - } class ThriftType extends ThriftNamedElement { - - ThriftType() { - kind.matches("%type") - } + ThriftType() { kind.matches("%type") } override ThriftElement getNameElement() { result = this.getChild(0) @@ -116,9 +80,7 @@ class ThriftType extends ThriftNamedElement { result = this.getChild(0).(ThriftType).getNameElement() } - override string toString() { - result = "type " + this.getName() - } + override string toString() { result = "type " + this.getName() } predicate references(ThriftStruct struct) { this.getName() = struct.getName() and @@ -127,194 +89,106 @@ class ThriftType extends ThriftNamedElement { struct.hasLocationInfo(path, _, _, _, _) ) } - } /** A thrift typedef */ class ThriftTypeDef extends ThriftNamedElement { + ThriftTypeDef() { kind.matches("typedef") } - ThriftTypeDef() { - kind.matches("typedef") - } - - override ThriftElement getNameElement() { - result = this.getChild(2).getChild(0) - } + override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) } } /** A thrift enum declaration */ class ThriftEnum extends ThriftNamedElement { + ThriftEnum() { kind.matches("enum") } - ThriftEnum() { - kind.matches("enum") - } - - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } } /** A thrift enum field */ class ThriftEnumField extends ThriftNamedElement { + ThriftEnumField() { kind.matches("enumfield") } - ThriftEnumField() { - kind.matches("enumfield") - } - - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } } /** A thrift service declaration */ class ThriftService extends ThriftNamedElement { + ThriftService() { kind.matches("service") } - ThriftService() { - kind.matches("service") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftFunction getAFunction() { - result = this.getChild(_) - } + ThriftFunction getAFunction() { result = this.getChild(_) } ThriftFunction getFunction(string name) { result.getName() = name and result = this.getAFunction() } - } /** A thrift function declaration */ class ThriftFunction extends ThriftNamedElement { + ThriftFunction() { kind.matches("function") } - ThriftFunction() { - kind.matches("function") - } + override ThriftElement getNameElement() { result = this.getChild(2).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(2).getChild(0) - } + ThriftField getArgument(int n) { result = this.getChild(n + 3) } - ThriftField getArgument(int n) { - result = this.getChild(n+3) - } + ThriftField getAnArgument() { result = this.getArgument(_) } - ThriftField getAnArgument() { - result = this.getArgument(_) - } + private ThriftThrows getAllThrows() { result = this.getChild(_) } - private ThriftThrows getAllThrows() { - result = this.getChild(_) - } + ThriftField getAThrows() { result = this.getAllThrows().getAChild() } - ThriftField getAThrows() { - result = this.getAllThrows().getAChild() - } - - ThriftType getReturnType() { - result = this.getChild(1).getChild(0) - } + ThriftType getReturnType() { result = this.getChild(1).getChild(0) } override predicate hasLocationInfo(string fp, int bl, int bc, int el, int ec) { this.getChild(1).hasLocationInfo(fp, bl, bc, _, _) and this.getChild(2).hasLocationInfo(fp, _, _, el, ec) } - ThriftService getService() { - result.getAFunction() = this - } - - string getQualifiedName() { - result = this.getService().getName() + "." + this.getName() - } + ThriftService getService() { result.getAFunction() = this } + string getQualifiedName() { result = this.getService().getName() + "." + this.getName() } } class ThriftField extends ThriftNamedElement { + ThriftField() { kind.matches("field") } - ThriftField() { - kind.matches("field") - } - - override ThriftElement getNameElement() { - result = this.getChild(4) - } - - ThriftType getType() { - result = this.getChild(2) - } + override ThriftElement getNameElement() { result = this.getChild(4) } + ThriftType getType() { result = this.getChild(2) } } -class ThriftStruct extends ThriftNamedElement { +class ThriftStruct extends ThriftNamedElement { + ThriftStruct() { kind.matches("struct") } - ThriftStruct() { - kind.matches("struct") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftField getMember(int n) { - result = this.getChild(n+1) - } - - ThriftField getAMember() { - result = this.getMember(_) - } + ThriftField getMember(int n) { result = this.getChild(n + 1) } + ThriftField getAMember() { result = this.getMember(_) } } - class ThriftException extends ThriftNamedElement { + ThriftException() { kind.matches("exception") } - ThriftException() { - kind.matches("exception") - } + override ThriftElement getNameElement() { result = this.getChild(0).getChild(0) } - override ThriftElement getNameElement() { - result = this.getChild(0).getChild(0) - } - - ThriftField getMember(int n) { - result = this.getChild(n+1) - } - - ThriftField getAMember() { - result = this.getMember(_) - } + ThriftField getMember(int n) { result = this.getChild(n + 1) } + ThriftField getAMember() { result = this.getMember(_) } } - class ThriftThrows extends ThriftElement { + ThriftThrows() { kind.matches("throws") } - ThriftThrows() { - kind.matches("throws") - } - - ThriftField getAThrows() { - result = this.getChild(_) - } - + ThriftField getAThrows() { result = this.getChild(_) } } /** A parse tree element that holds a primitive value */ class ThriftValue extends ThriftElement { + ThriftValue() { exists(this.getValue()) } - ThriftValue() { - exists(this.getValue()) - } - - override string toString() { - result = this.getKind() + " " + this.getValue() - } - + override string toString() { result = this.getKind() + " " + this.getValue() } } diff --git a/python/ql/src/external/VCS.qll b/python/ql/src/external/VCS.qll index 6b665dde510..0212dbfbd24 100644 --- a/python/ql/src/external/VCS.qll +++ b/python/ql/src/external/VCS.qll @@ -1,92 +1,76 @@ import python class Commit extends @svnentry { + Commit() { + svnaffectedfiles(this, _, _) and + exists(date svnDate, date snapshotDate | + svnentries(this, _, _, svnDate, _) and + snapshotDate(snapshotDate) and + svnDate <= snapshotDate + ) + } - Commit() { - svnaffectedfiles(this, _, _) and - exists(date svnDate, date snapshotDate | - svnentries(this, _, _, svnDate, _) and - snapshotDate(snapshotDate) and - svnDate <= snapshotDate - ) - } + string toString() { result = this.getRevisionName() } - string toString() { result = this.getRevisionName() } + string getRevisionName() { svnentries(this, result, _, _, _) } - string getRevisionName() { svnentries(this, result, _, _, _) } - - string getAuthor() { svnentries(this, _, result, _, _) } - - date getDate() { svnentries(this, _, _, result, _) } - - int getChangeSize() { svnentries(this, _, _, _, result) } - - string getMessage() { svnentrymsg(this, result) } - - string getAnAffectedFilePath(string action) { - exists(File rawFile | svnaffectedfiles(this, rawFile, action) | - result = rawFile.getName() - ) - } - - string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } - - File getAnAffectedFile(string action) { - svnaffectedfiles(this,result,action) - } + string getAuthor() { svnentries(this, _, result, _, _) } - File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } + date getDate() { svnentries(this, _, _, result, _) } - predicate isRecent() { recentCommit(this) } - - int daysToNow() { - exists(date now | snapshotDate(now) | - result = getDate().daysTo(now) and result >= 0 - ) - } - - int getRecentAdditionsForFile(File f) { - svnchurn(this, f, result, _) - } - - int getRecentDeletionsForFile(File f) { - svnchurn(this, f, _, result) - } + int getChangeSize() { svnentries(this, _, _, _, result) } - int getRecentChurnForFile(File f) { - result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f) - } + string getMessage() { svnentrymsg(this, result) } + string getAnAffectedFilePath(string action) { + exists(File rawFile | svnaffectedfiles(this, rawFile, action) | result = rawFile.getAbsolutePath()) + } + + string getAnAffectedFilePath() { result = getAnAffectedFilePath(_) } + + File getAnAffectedFile(string action) { svnaffectedfiles(this, result, action) } + + File getAnAffectedFile() { exists(string action | result = this.getAnAffectedFile(action)) } + + predicate isRecent() { recentCommit(this) } + + int daysToNow() { + exists(date now | snapshotDate(now) | result = getDate().daysTo(now) and result >= 0) + } + + int getRecentAdditionsForFile(File f) { svnchurn(this, f, result, _) } + + int getRecentDeletionsForFile(File f) { svnchurn(this, f, _, result) } + + int getRecentChurnForFile(File f) { + result = getRecentAdditionsForFile(f) + getRecentDeletionsForFile(f) + } } class Author extends string { - Author() { exists(Commit e | this = e.getAuthor()) } - - Commit getACommit() { result.getAuthor() = this } - - File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } - + Author() { exists(Commit e | this = e.getAuthor()) } + + Commit getACommit() { result.getAuthor() = this } + + File getAnEditedFile() { result = this.getACommit().getAnAffectedFile() } } predicate recentCommit(Commit e) { - exists(date snapshotDate, date commitDate, int days | - snapshotDate(snapshotDate) and - e.getDate() = commitDate and - days = commitDate.daysTo(snapshotDate) and - days >= 0 and days <= 60 - ) + exists(date snapshotDate, date commitDate, int days | + snapshotDate(snapshotDate) and + e.getDate() = commitDate and + days = commitDate.daysTo(snapshotDate) and + days >= 0 and + days <= 60 + ) } date firstChange(File f) { - result = min(Commit e, date toMin | (f = e.getAnAffectedFile()) and (toMin = e.getDate()) | toMin) + result = min(Commit e, date toMin | f = e.getAnAffectedFile() and toMin = e.getDate() | toMin) } predicate firstCommit(Commit e) { - not exists(File f | f = e.getAnAffectedFile() | - firstChange(f) < e.getDate() - ) + not exists(File f | f = e.getAnAffectedFile() | firstChange(f) < e.getDate()) } -predicate artificialChange(Commit e) { - firstCommit(e) or e.getChangeSize() >= 50000 -} \ No newline at end of file +predicate artificialChange(Commit e) { firstCommit(e) or e.getChangeSize() >= 50000 } diff --git a/python/ql/src/python.qll b/python/ql/src/python.qll index d1c096ff4ac..6cf0802d993 100644 --- a/python/ql/src/python.qll +++ b/python/ql/src/python.qll @@ -34,5 +34,4 @@ import semmle.python.pointsto.Base import semmle.python.pointsto.Context import semmle.python.pointsto.CallGraph import semmle.python.objects.ObjectAPI - import site diff --git a/python/ql/src/qlpack.yml b/python/ql/src/qlpack.yml index 23027b6d95e..9807b169d44 100644 --- a/python/ql/src/qlpack.yml +++ b/python/ql/src/qlpack.yml @@ -2,3 +2,4 @@ name: codeql-python version: 0.0.0 dbscheme: semmlecode.python.dbscheme suites: codeql-suites +extractor: python diff --git a/python/ql/src/semmle/crypto/Crypto.qll b/python/ql/src/semmle/crypto/Crypto.qll index 12e81a393ce..4eaa3eb8dbd 100644 --- a/python/ql/src/semmle/crypto/Crypto.qll +++ b/python/ql/src/semmle/crypto/Crypto.qll @@ -2,10 +2,10 @@ * Provides classes for modeling cryptographic libraries. */ -/* The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll` +/* + * The following information is copied from `/semmlecode-javascript-queries/semmle/javascript/frameworks/CryptoLibraries.qll` * which should be considered the definitive version (as of Feb 2018) */ - /** * Names of cryptographic algorithms, separated into strong and weak variants. @@ -13,15 +13,17 @@ * The names are normalized: upper-case, no spaces, dashes or underscores. * * The names are inspired by the names used in real world crypto libraries. - * */ private module AlgorithmNames { predicate isStrongHashingAlgorithm(string name) { name = "DSA" or name = "ED25519" or - name = "ES256" or name = "ECDSA256" or - name = "ES384" or name = "ECDSA384" or - name = "ES512" or name = "ECDSA512" or + name = "ES256" or + name = "ECDSA256" or + name = "ES384" or + name = "ECDSA384" or + name = "ES512" or + name = "ECDSA512" or name = "SHA2" or name = "SHA224" or name = "SHA256" or @@ -54,15 +56,21 @@ private module AlgorithmNames { name = "RSA" or name = "RABBIT" or name = "BLOWFISH" - } predicate isWeakEncryptionAlgorithm(string name) { name = "DES" or - name = "3DES" or name = "TRIPLEDES" or name = "TDEA" or name = "TRIPLEDEA" or - name = "ARC2" or name = "RC2" or - name = "ARC4" or name = "RC4" or name = "ARCFOUR" or - name = "ARC5" or name = "RC5" + name = "3DES" or + name = "TRIPLEDES" or + name = "TDEA" or + name = "TRIPLEDEA" or + name = "ARC2" or + name = "RC2" or + name = "ARC4" or + name = "RC4" or + name = "ARCFOUR" or + name = "ARC5" or + name = "RC5" } predicate isStrongPasswordHashingAlgorithm(string name) { @@ -72,51 +80,45 @@ private module AlgorithmNames { name = "SCRYPT" } - predicate isWeakPasswordHashingAlgorithm(string name) { - none() - } + predicate isWeakPasswordHashingAlgorithm(string name) { none() } /** * Normalizes `name`: upper-case, no spaces, dashes or underscores. * * All names of this module are in this normalized form. */ - bindingset[name] string normalizeName(string name) { - result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") - } - + bindingset[name] + string normalizeName(string name) { result = name.toUpperCase().regexpReplaceAll("[-_ ]", "") } } -private import AlgorithmNames +private import AlgorithmNames /** * A cryptographic algorithm. */ private newtype TCryptographicAlgorithm = -MkHashingAlgorithm(string name, boolean isWeak) { - (isStrongHashingAlgorithm(name) and isWeak = false) or - (isWeakHashingAlgorithm(name) and isWeak = true) -} -or -MkEncryptionAlgorithm(string name, boolean isWeak) { - (isStrongEncryptionAlgorithm(name) and isWeak = false) or - (isWeakEncryptionAlgorithm(name) and isWeak = true) -} -or -MkPasswordHashingAlgorithm(string name, boolean isWeak) { - (isStrongPasswordHashingAlgorithm(name) and isWeak = false) or - (isWeakPasswordHashingAlgorithm(name) and isWeak = true) -} + MkHashingAlgorithm(string name, boolean isWeak) { + isStrongHashingAlgorithm(name) and isWeak = false + or + isWeakHashingAlgorithm(name) and isWeak = true + } or + MkEncryptionAlgorithm(string name, boolean isWeak) { + isStrongEncryptionAlgorithm(name) and isWeak = false + or + isWeakEncryptionAlgorithm(name) and isWeak = true + } or + MkPasswordHashingAlgorithm(string name, boolean isWeak) { + isStrongPasswordHashingAlgorithm(name) and isWeak = false + or + isWeakPasswordHashingAlgorithm(name) and isWeak = true + } /** * A cryptographic algorithm. */ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { - /** Gets a textual representation of this element. */ - string toString() { - result = getName() - } + string toString() { result = getName() } /** * Gets the name of the algorithm. @@ -127,76 +129,46 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm { * Holds if this algorithm is weak. */ abstract predicate isWeak(); - } /** * A hashing algorithm such as `MD5` or `SHA512`. */ class HashingAlgorithm extends MkHashingAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - HashingAlgorithm() { - this = MkHashingAlgorithm(name, isWeak) - } + HashingAlgorithm() { this = MkHashingAlgorithm(name, isWeak) } - override string getName() { - result = name - } - - override predicate isWeak() { - isWeak = true - } + override string getName() { result = name } + override predicate isWeak() { isWeak = true } } /** * An encryption algorithm such as `DES` or `AES512`. */ class EncryptionAlgorithm extends MkEncryptionAlgorithm, CryptographicAlgorithm { - string name; - boolean isWeak; - EncryptionAlgorithm() { - this = MkEncryptionAlgorithm(name, isWeak) - } + EncryptionAlgorithm() { this = MkEncryptionAlgorithm(name, isWeak) } - override string getName() { - result = name - } - - override predicate isWeak() { - isWeak = true - } + override string getName() { result = name } + override predicate isWeak() { isWeak = true } } /** * A password hashing algorithm such as `PBKDF2` or `SCRYPT`. */ -class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { - +class PasswordHashingAlgorithm extends MkPasswordHashingAlgorithm, CryptographicAlgorithm { string name; - boolean isWeak; - PasswordHashingAlgorithm() { - this = MkPasswordHashingAlgorithm(name, isWeak) - } + PasswordHashingAlgorithm() { this = MkPasswordHashingAlgorithm(name, isWeak) } - override string getName() { - result = name - } + override string getName() { result = name } - override predicate isWeak() { - isWeak = true - } + override predicate isWeak() { isWeak = true } } - - - diff --git a/python/ql/src/semmle/files/FileSystem.qll b/python/ql/src/semmle/files/FileSystem.qll index 4ec67c7c2e6..4e28b33d96d 100644 --- a/python/ql/src/semmle/files/FileSystem.qll +++ b/python/ql/src/semmle/files/FileSystem.qll @@ -1,2 +1,3 @@ /** Provides classes for working with files and folders. */ + import semmle.python.Files diff --git a/python/ql/src/semmle/python/AstExtended.qll b/python/ql/src/semmle/python/AstExtended.qll index 65bc653bfd5..8a858c5fefc 100644 --- a/python/ql/src/semmle/python/AstExtended.qll +++ b/python/ql/src/semmle/python/AstExtended.qll @@ -2,55 +2,52 @@ import python /** Syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */ abstract class AstNode extends AstNode_ { - - /* Special comment for documentation generation. + /* + * Special comment for documentation generation. * All subclasses of `AstNode` that represent concrete syntax should have - * a comment of the form: */ - /* syntax: ... */ + * a comment of the form: + */ + /* syntax: ... */ /** Gets the scope that this node occurs in */ abstract Scope getScope(); - /** Gets a flow node corresponding directly to this node. + /** + * Gets a flow node corresponding directly to this node. * NOTE: For some statements and other purely syntactic elements, - * there may not be a `ControlFlowNode` */ - ControlFlowNode getAFlowNode() { - py_flow_bb_node(result, this, _, _) - } + * there may not be a `ControlFlowNode` + */ + ControlFlowNode getAFlowNode() { py_flow_bb_node(result, this, _, _) } /** Gets the location for this AST node */ - Location getLocation() { - none() - } + Location getLocation() { none() } - /** Whether this syntactic element is artificial, that is it is generated - * by the compiler and is not present in the source */ - predicate isArtificial() { - none() - } + /** + * Whether this syntactic element is artificial, that is it is generated + * by the compiler and is not present in the source + */ + predicate isArtificial() { none() } - /** Gets a child node of this node in the AST. This predicate exists to aid exploration of the AST - * and other experiments. The child-parent relation may not be meaningful. - * For a more meaningful relation in terms of dependency use - * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or - * Scope.getAStmt(). - */ + /** + * Gets a child node of this node in the AST. This predicate exists to aid exploration of the AST + * and other experiments. The child-parent relation may not be meaningful. + * For a more meaningful relation in terms of dependency use + * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or + * Scope.getAStmt(). + */ abstract AstNode getAChildNode(); - /** Gets the parent node of this node in the AST. This predicate exists to aid exploration of the AST - * and other experiments. The child-parent relation may not be meaningful. - * For a more meaningful relation in terms of dependency use - * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or - * Scope.getAStmt() applied to the parent. - */ - AstNode getParentNode() { - result.getAChildNode() = this - } + /** + * Gets the parent node of this node in the AST. This predicate exists to aid exploration of the AST + * and other experiments. The child-parent relation may not be meaningful. + * For a more meaningful relation in terms of dependency use + * Expr.getASubExpression(), Stmt.getASubStatement(), Stmt.getASubExpression() or + * Scope.getAStmt() applied to the parent. + */ + AstNode getParentNode() { result.getAChildNode() = this } /** Whether this contains `inner` syntactically */ - predicate contains(AstNode inner) { - this.getAChildNode+() = inner - } + predicate contains(AstNode inner) { this.getAChildNode+() = inner } /** Whether this contains `inner` syntactically and `inner` has the same scope as `this` */ predicate containsInScope(AstNode inner) { @@ -58,133 +55,86 @@ abstract class AstNode extends AstNode_ { this.getScope() = inner.getScope() and not inner instanceof Scope } - } /* Parents */ +/** Internal implementation class */ +library class FunctionParent extends FunctionParent_ { } /** Internal implementation class */ -library class FunctionParent extends FunctionParent_ { - -} +library class ArgumentsParent extends ArgumentsParent_ { } /** Internal implementation class */ -library class ArgumentsParent extends ArgumentsParent_ { - -} +library class ExprListParent extends ExprListParent_ { } /** Internal implementation class */ -library class ExprListParent extends ExprListParent_ { - -} +library class ExprContextParent extends ExprContextParent_ { } /** Internal implementation class */ -library class ExprContextParent extends ExprContextParent_ { - -} +library class StmtListParent extends StmtListParent_ { } /** Internal implementation class */ -library class StmtListParent extends StmtListParent_ { - -} +library class StrListParent extends StrListParent_ { } /** Internal implementation class */ -library class StrListParent extends StrListParent_ { - -} - -/** Internal implementation class */ -library class ExprParent extends ExprParent_ { - -} +library class ExprParent extends ExprParent_ { } library class DictItem extends DictItem_, AstNode { - - override string toString() { - result = DictItem_.super.toString() - } + override string toString() { result = DictItem_.super.toString() } override AstNode getAChildNode() { none() } override Scope getScope() { none() } - } /** A comprehension part, the 'for a in seq' part of [ a * a for a in seq ] */ class Comprehension extends Comprehension_, AstNode { - /** Gets the scope of this comprehension */ override Scope getScope() { /* Comprehensions exists only in Python 2 list comprehensions, so their scope is that of the list comp. */ - exists(ListComp l | - this = l.getAGenerator() | - result = l.getScope() - ) + exists(ListComp l | this = l.getAGenerator() | result = l.getScope()) } - override string toString() { - result = "Comprehension" - } + override string toString() { result = "Comprehension" } - override Location getLocation() { - result = Comprehension_.super.getLocation() - } + override Location getLocation() { result = Comprehension_.super.getLocation() } - override AstNode getAChildNode() { - result = this.getASubExpression() - } + override AstNode getAChildNode() { result = this.getASubExpression() } Expr getASubExpression() { result = this.getIter() or result = this.getAnIf() or result = this.getTarget() } - } -class BytesOrStr extends BytesOrStr_ { +class BytesOrStr extends BytesOrStr_ { } -} - -/** Part of a string literal formed by implicit concatenation. +/** + * Part of a string literal formed by implicit concatenation. * For example the string literal "abc" expressed in the source as `"a" "b" "c"` * would be composed of three `StringPart`s. - * */ class StringPart extends StringPart_, AstNode { - override Scope getScope() { exists(Bytes b | this = b.getAnImplicitlyConcatenatedPart() | result = b.getScope()) or exists(Unicode u | this = u.getAnImplicitlyConcatenatedPart() | result = u.getScope()) } - override AstNode getAChildNode() { - none() - } + override AstNode getAChildNode() { none() } - override string toString() { - result = StringPart_.super.toString() - } - - override Location getLocation() { - result = StringPart_.super.getLocation() - } + override string toString() { result = StringPart_.super.toString() } + override Location getLocation() { result = StringPart_.super.getLocation() } } -class StringPartList extends StringPartList_ { - -} +class StringPartList extends StringPartList_ { } /* **** Lists ***/ - /** A parameter list */ class ParameterList extends @py_parameter_list { - - Function getParent() { - py_parameter_lists(this, result) - } + Function getParent() { py_parameter_lists(this, result) } /** Gets a parameter */ Parameter getAnItem() { @@ -198,40 +148,23 @@ class ParameterList extends @py_parameter_list { py_exprs(result, _, this, index) } - string toString() { - result = "ParameterList" - } + string toString() { result = "ParameterList" } } /** A list of Comprehensions (for generating parts of a set, list or dictionary comprehension) */ -class ComprehensionList extends ComprehensionList_ { - -} +class ComprehensionList extends ComprehensionList_ { } /** A list of expressions */ class ExprList extends ExprList_ { - /* syntax: Expr, ... */ - } +library class DictItemList extends DictItemList_ { } -library class DictItemList extends DictItemList_ { - -} - -library class DictItemListParent extends DictItemListParent_ { - -} +library class DictItemListParent extends DictItemListParent_ { } /** A list of strings (the primitive type string not Bytes or Unicode) */ -class StringList extends StringList_ { - -} +class StringList extends StringList_ { } /** A list of aliases in an import statement */ -class AliasList extends AliasList_ { - -} - - +class AliasList extends AliasList_ { } diff --git a/python/ql/src/semmle/python/AstGenerated.qll b/python/ql/src/semmle/python/AstGenerated.qll index 6832b3f2da6..13e803650cc 100644 --- a/python/ql/src/semmle/python/AstGenerated.qll +++ b/python/ql/src/semmle/python/AstGenerated.qll @@ -3,304 +3,157 @@ * WARNING: Any modifications to this file will be lost. * Relations can be changed by modifying master.py. */ + import python library class Add_ extends @py_Add, Operator { - - override string toString() { - result = "Add" - } - + override string toString() { result = "Add" } } library class And_ extends @py_And, Boolop { - - override string toString() { - result = "And" - } - + override string toString() { result = "And" } } library class AnnAssign_ extends @py_AnnAssign, Stmt { - - /** Gets the value of this annotated assignment. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the annotation of this annotated assignment. */ - Expr getAnnotation() { - py_exprs(result, _, this, 2) - } - + Expr getAnnotation() { py_exprs(result, _, this, 2) } /** Gets the target of this annotated assignment. */ - Expr getTarget() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "AnnAssign" - } + Expr getTarget() { py_exprs(result, _, this, 3) } + override string toString() { result = "AnnAssign" } } library class Assert_ extends @py_Assert, Stmt { - - /** Gets the value being tested of this assert statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the failure message of this assert statement. */ - Expr getMsg() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Assert" - } + Expr getMsg() { py_exprs(result, _, this, 2) } + override string toString() { result = "Assert" } } library class Assign_ extends @py_Assign, Stmt { - - /** Gets the value of this assignment statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the targets of this assignment statement. */ - ExprList getTargets() { - py_expr_lists(result, this, 2) - } - + ExprList getTargets() { py_expr_lists(result, this, 2) } /** Gets the nth target of this assignment statement. */ - Expr getTarget(int index) { - result = this.getTargets().getItem(index) - } + Expr getTarget(int index) { result = this.getTargets().getItem(index) } /** Gets a target of this assignment statement. */ - Expr getATarget() { - result = this.getTargets().getAnItem() - } - - override string toString() { - result = "Assign" - } + Expr getATarget() { result = this.getTargets().getAnItem() } + override string toString() { result = "Assign" } } library class AssignExpr_ extends @py_AssignExpr, Expr { - - /** Gets the value of this assignment expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the target of this assignment expression. */ - Expr getTarget() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "AssignExpr" - } + Expr getTarget() { py_exprs(result, _, this, 3) } + override string toString() { result = "AssignExpr" } } library class Attribute_ extends @py_Attribute, Expr { - - /** Gets the object of this attribute expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the attribute name of this attribute expression. */ - string getAttr() { - py_strs(result, this, 3) - } - + string getAttr() { py_strs(result, this, 3) } /** Gets the context of this attribute expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Attribute" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Attribute" } } library class AugAssign_ extends @py_AugAssign, Stmt { - - /** Gets the operation of this augmented assignment statement. */ - BinaryExpr getOperation() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "AugAssign" - } + BinaryExpr getOperation() { py_exprs(result, _, this, 1) } + override string toString() { result = "AugAssign" } } library class AugLoad_ extends @py_AugLoad, ExprContext { - - override string toString() { - result = "AugLoad" - } - + override string toString() { result = "AugLoad" } } library class AugStore_ extends @py_AugStore, ExprContext { - - override string toString() { - result = "AugStore" - } - + override string toString() { result = "AugStore" } } library class Await_ extends @py_Await, Expr { - - /** Gets the expression waited upon of this await expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Await" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Await" } } library class BinaryExpr_ extends @py_BinaryExpr, Expr { - - /** Gets the left sub-expression of this binary expression. */ - Expr getLeft() { - py_exprs(result, _, this, 2) - } - + Expr getLeft() { py_exprs(result, _, this, 2) } /** Gets the operator of this binary expression. */ - Operator getOp() { - py_operators(result, _, this) - } - + Operator getOp() { py_operators(result, _, this) } /** Gets the right sub-expression of this binary expression. */ - Expr getRight() { - py_exprs(result, _, this, 4) - } + Expr getRight() { py_exprs(result, _, this, 4) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "BinaryExpr" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "BinaryExpr" } } library class BitAnd_ extends @py_BitAnd, Operator { - - override string toString() { - result = "BitAnd" - } - + override string toString() { result = "BitAnd" } } library class BitOr_ extends @py_BitOr, Operator { - - override string toString() { - result = "BitOr" - } - + override string toString() { result = "BitOr" } } library class BitXor_ extends @py_BitXor, Operator { - - override string toString() { - result = "BitXor" - } - + override string toString() { result = "BitXor" } } library class BoolExpr_ extends @py_BoolExpr, Expr { - - /** Gets the operator of this boolean expression. */ - Boolop getOp() { - py_boolops(result, _, this) - } - + Boolop getOp() { py_boolops(result, _, this) } /** Gets the sub-expressions of this boolean expression. */ - ExprList getValues() { - py_expr_lists(result, this, 3) - } - + ExprList getValues() { py_expr_lists(result, this, 3) } /** Gets the nth sub-expression of this boolean expression. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a sub-expression of this boolean expression. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } - - override string toString() { - result = "BoolExpr" - } + Expr getAValue() { result = this.getValues().getAnItem() } + override string toString() { result = "BoolExpr" } } library class Break_ extends @py_Break, Stmt { - - override string toString() { - result = "Break" - } - + override string toString() { result = "Break" } } library class Bytes_ extends @py_Bytes, Expr { - - /** Gets the value of this bytes expression. */ - string getS() { - py_bytes(result, this, 2) - } - + string getS() { py_bytes(result, this, 2) } /** Gets the prefix of this bytes expression. */ - string getPrefix() { - py_bytes(result, this, 3) - } - + string getPrefix() { py_bytes(result, this, 3) } /** Gets the implicitly_concatenated_parts of this bytes expression. */ - StringPartList getImplicitlyConcatenatedParts() { - py_StringPart_lists(result, this) - } - + StringPartList getImplicitlyConcatenatedParts() { py_StringPart_lists(result, this) } /** Gets the nth implicitly_concatenated_part of this bytes expression. */ StringPart getImplicitlyConcatenatedPart(int index) { @@ -312,1559 +165,795 @@ library class Bytes_ extends @py_Bytes, Expr { result = this.getImplicitlyConcatenatedParts().getAnItem() } - override string toString() { - result = "Bytes" - } - + override string toString() { result = "Bytes" } } library class BytesOrStr_ extends @py_Bytes_or_Str { - - string toString() { - result = "BytesOrStr" - } - + string toString() { result = "BytesOrStr" } } library class Call_ extends @py_Call, Expr { - - /** Gets the callable of this call expression. */ - Expr getFunc() { - py_exprs(result, _, this, 2) - } - + Expr getFunc() { py_exprs(result, _, this, 2) } /** Gets the positional arguments of this call expression. */ - ExprList getPositionalArgs() { - py_expr_lists(result, this, 3) - } - + ExprList getPositionalArgs() { py_expr_lists(result, this, 3) } /** Gets the nth positional argument of this call expression. */ - Expr getPositionalArg(int index) { - result = this.getPositionalArgs().getItem(index) - } + Expr getPositionalArg(int index) { result = this.getPositionalArgs().getItem(index) } /** Gets a positional argument of this call expression. */ - Expr getAPositionalArg() { - result = this.getPositionalArgs().getAnItem() - } - + Expr getAPositionalArg() { result = this.getPositionalArgs().getAnItem() } /** Gets the named arguments of this call expression. */ - DictItemList getNamedArgs() { - py_dict_item_lists(result, this) - } - + DictItemList getNamedArgs() { py_dict_item_lists(result, this) } /** Gets the nth named argument of this call expression. */ - DictItem getNamedArg(int index) { - result = this.getNamedArgs().getItem(index) - } + DictItem getNamedArg(int index) { result = this.getNamedArgs().getItem(index) } /** Gets a named argument of this call expression. */ - DictItem getANamedArg() { - result = this.getNamedArgs().getAnItem() - } - - override string toString() { - result = "Call" - } + DictItem getANamedArg() { result = this.getNamedArgs().getAnItem() } + override string toString() { result = "Call" } } library class Class_ extends @py_Class { - - /** Gets the name of this class. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the body of this class. */ - StmtList getBody() { - py_stmt_lists(result, this, 1) - } - + StmtList getBody() { py_stmt_lists(result, this, 1) } /** Gets the nth statement of this class. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this class. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } + Stmt getAStmt() { result = this.getBody().getAnItem() } - ClassExpr getParent() { - py_Classes(this, result) - } - - string toString() { - result = "Class" - } + ClassExpr getParent() { py_Classes(this, result) } + string toString() { result = "Class" } } library class ClassExpr_ extends @py_ClassExpr, Expr { - - /** Gets the name of this class definition. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the bases of this class definition. */ - ExprList getBases() { - py_expr_lists(result, this, 3) - } - + ExprList getBases() { py_expr_lists(result, this, 3) } /** Gets the nth base of this class definition. */ - Expr getBase(int index) { - result = this.getBases().getItem(index) - } + Expr getBase(int index) { result = this.getBases().getItem(index) } /** Gets a base of this class definition. */ - Expr getABase() { - result = this.getBases().getAnItem() - } - + Expr getABase() { result = this.getBases().getAnItem() } /** Gets the keyword arguments of this class definition. */ - DictItemList getKeywords() { - py_dict_item_lists(result, this) - } - + DictItemList getKeywords() { py_dict_item_lists(result, this) } /** Gets the nth keyword argument of this class definition. */ - DictItem getKeyword(int index) { - result = this.getKeywords().getItem(index) - } + DictItem getKeyword(int index) { result = this.getKeywords().getItem(index) } /** Gets a keyword argument of this class definition. */ - DictItem getAKeyword() { - result = this.getKeywords().getAnItem() - } - + DictItem getAKeyword() { result = this.getKeywords().getAnItem() } /** Gets the class scope of this class definition. */ - Class getInnerScope() { - py_Classes(result, this) - } - - override string toString() { - result = "ClassExpr" - } + Class getInnerScope() { py_Classes(result, this) } + override string toString() { result = "ClassExpr" } } library class Compare_ extends @py_Compare, Expr { - - /** Gets the left sub-expression of this compare expression. */ - Expr getLeft() { - py_exprs(result, _, this, 2) - } - + Expr getLeft() { py_exprs(result, _, this, 2) } /** Gets the comparison operators of this compare expression. */ - CmpopList getOps() { - py_cmpop_lists(result, this) - } - + CmpopList getOps() { py_cmpop_lists(result, this) } /** Gets the nth comparison operator of this compare expression. */ - Cmpop getOp(int index) { - result = this.getOps().getItem(index) - } + Cmpop getOp(int index) { result = this.getOps().getItem(index) } /** Gets a comparison operator of this compare expression. */ - Cmpop getAnOp() { - result = this.getOps().getAnItem() - } - + Cmpop getAnOp() { result = this.getOps().getAnItem() } /** Gets the right sub-expressions of this compare expression. */ - ExprList getComparators() { - py_expr_lists(result, this, 4) - } - + ExprList getComparators() { py_expr_lists(result, this, 4) } /** Gets the nth right sub-expression of this compare expression. */ - Expr getComparator(int index) { - result = this.getComparators().getItem(index) - } + Expr getComparator(int index) { result = this.getComparators().getItem(index) } /** Gets a right sub-expression of this compare expression. */ - Expr getAComparator() { - result = this.getComparators().getAnItem() - } - - override string toString() { - result = "Compare" - } + Expr getAComparator() { result = this.getComparators().getAnItem() } + override string toString() { result = "Compare" } } library class Continue_ extends @py_Continue, Stmt { - - override string toString() { - result = "Continue" - } - + override string toString() { result = "Continue" } } library class Del_ extends @py_Del, ExprContext { - - override string toString() { - result = "Del" - } - + override string toString() { result = "Del" } } library class Delete_ extends @py_Delete, Stmt { - - /** Gets the targets of this delete statement. */ - ExprList getTargets() { - py_expr_lists(result, this, 1) - } - + ExprList getTargets() { py_expr_lists(result, this, 1) } /** Gets the nth target of this delete statement. */ - Expr getTarget(int index) { - result = this.getTargets().getItem(index) - } + Expr getTarget(int index) { result = this.getTargets().getItem(index) } /** Gets a target of this delete statement. */ - Expr getATarget() { - result = this.getTargets().getAnItem() - } - - override string toString() { - result = "Delete" - } + Expr getATarget() { result = this.getTargets().getAnItem() } + override string toString() { result = "Delete" } } library class Dict_ extends @py_Dict, Expr { - - /** Gets the items of this dictionary expression. */ - DictItemList getItems() { - py_dict_item_lists(result, this) - } - + DictItemList getItems() { py_dict_item_lists(result, this) } /** Gets the nth item of this dictionary expression. */ - DictItem getItem(int index) { - result = this.getItems().getItem(index) - } + DictItem getItem(int index) { result = this.getItems().getItem(index) } /** Gets an item of this dictionary expression. */ - DictItem getAnItem() { - result = this.getItems().getAnItem() - } - - override string toString() { - result = "Dict" - } + DictItem getAnItem() { result = this.getItems().getAnItem() } + override string toString() { result = "Dict" } } library class DictComp_ extends @py_DictComp, Expr { - - /** Gets the implementation of this dictionary comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this dictionary comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "DictComp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "DictComp" } } library class DictUnpacking_ extends @py_DictUnpacking, DictItem { - - /** Gets the location of this dictionary unpacking. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this dictionary unpacking. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "DictUnpacking" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "DictUnpacking" } } library class Div_ extends @py_Div, Operator { - - override string toString() { - result = "Div" - } - + override string toString() { result = "Div" } } library class Ellipsis_ extends @py_Ellipsis, Expr { - - override string toString() { - result = "Ellipsis" - } - + override string toString() { result = "Ellipsis" } } library class Eq_ extends @py_Eq, Cmpop { - - override string toString() { - result = "Eq" - } - + override string toString() { result = "Eq" } } library class ExceptStmt_ extends @py_ExceptStmt, Stmt { - - /** Gets the type of this except block. */ - Expr getType() { - py_exprs(result, _, this, 1) - } - + Expr getType() { py_exprs(result, _, this, 1) } /** Gets the name of this except block. */ - Expr getName() { - py_exprs(result, _, this, 2) - } - + Expr getName() { py_exprs(result, _, this, 2) } /** Gets the body of this except block. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this except block. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this except block. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - - override string toString() { - result = "ExceptStmt" - } + Stmt getAStmt() { result = this.getBody().getAnItem() } + override string toString() { result = "ExceptStmt" } } library class Exec_ extends @py_Exec, Stmt { - - /** Gets the body of this exec statement. */ - Expr getBody() { - py_exprs(result, _, this, 1) - } - + Expr getBody() { py_exprs(result, _, this, 1) } /** Gets the globals of this exec statement. */ - Expr getGlobals() { - py_exprs(result, _, this, 2) - } - + Expr getGlobals() { py_exprs(result, _, this, 2) } /** Gets the locals of this exec statement. */ - Expr getLocals() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "Exec" - } + Expr getLocals() { py_exprs(result, _, this, 3) } + override string toString() { result = "Exec" } } library class ExprStmt_ extends @py_Expr_stmt, Stmt { - - /** Gets the value of this expr statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "ExprStmt" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "ExprStmt" } } library class Filter_ extends @py_Filter, Expr { - - /** Gets the filtered value of this template filter expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the filter of this template filter expression. */ - Expr getFilter() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "Filter" - } + Expr getFilter() { py_exprs(result, _, this, 3) } + override string toString() { result = "Filter" } } library class FloorDiv_ extends @py_FloorDiv, Operator { - - override string toString() { - result = "FloorDiv" - } - + override string toString() { result = "FloorDiv" } } library class For_ extends @py_For, Stmt { - - /** Gets the target of this for statement. */ - Expr getTarget() { - py_exprs(result, _, this, 1) - } - + Expr getTarget() { py_exprs(result, _, this, 1) } /** Gets the iterable of this for statement. */ - Expr getIter() { - py_exprs(result, _, this, 2) - } - + Expr getIter() { py_exprs(result, _, this, 2) } /** Gets the body of this for statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this for statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this for statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this for statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 4) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 4) } /** Gets the nth else statement of this for statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this for statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } /** Whether the async property of this for statement is true. */ - predicate isAsync() { - py_bools(this, 5) - } - - override string toString() { - result = "For" - } + predicate isAsync() { py_bools(this, 5) } + override string toString() { result = "For" } } library class FormattedValue_ extends @py_FormattedValue, Expr { - - /** Gets the expression to be formatted of this formatted value. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the type conversion of this formatted value. */ - string getConversion() { - py_strs(result, this, 3) - } - + string getConversion() { py_strs(result, this, 3) } /** Gets the format specifier of this formatted value. */ - Fstring getFormatSpec() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "FormattedValue" - } + Fstring getFormatSpec() { py_exprs(result, _, this, 4) } + override string toString() { result = "FormattedValue" } } library class Function_ extends @py_Function { - - /** Gets the name of this function. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the positional parameter list of this function. */ - ParameterList getArgs() { - py_parameter_lists(result, this) - } - + ParameterList getArgs() { py_parameter_lists(result, this) } /** Gets the nth positional parameter of this function. */ - Parameter getArg(int index) { - result = this.getArgs().getItem(index) - } + Parameter getArg(int index) { result = this.getArgs().getItem(index) } /** Gets a positional parameter of this function. */ - Parameter getAnArg() { - result = this.getArgs().getAnItem() - } - + Parameter getAnArg() { result = this.getArgs().getAnItem() } /** Gets the tuple (*) parameter of this function. */ - Expr getVararg() { - py_exprs(result, _, this, 2) - } - + Expr getVararg() { py_exprs(result, _, this, 2) } /** Gets the keyword-only parameter list of this function. */ - ExprList getKwonlyargs() { - py_expr_lists(result, this, 3) - } - + ExprList getKwonlyargs() { py_expr_lists(result, this, 3) } /** Gets the nth keyword-only parameter of this function. */ - Expr getKwonlyarg(int index) { - result = this.getKwonlyargs().getItem(index) - } + Expr getKwonlyarg(int index) { result = this.getKwonlyargs().getItem(index) } /** Gets a keyword-only parameter of this function. */ - Expr getAKwonlyarg() { - result = this.getKwonlyargs().getAnItem() - } - + Expr getAKwonlyarg() { result = this.getKwonlyargs().getAnItem() } /** Gets the dictionary (**) parameter of this function. */ - Expr getKwarg() { - py_exprs(result, _, this, 4) - } - + Expr getKwarg() { py_exprs(result, _, this, 4) } /** Gets the body of this function. */ - StmtList getBody() { - py_stmt_lists(result, this, 5) - } - + StmtList getBody() { py_stmt_lists(result, this, 5) } /** Gets the nth statement of this function. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this function. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Whether the async property of this function is true. */ - predicate isAsync() { - py_bools(this, 6) - } + predicate isAsync() { py_bools(this, 6) } - FunctionParent getParent() { - py_Functions(this, result) - } - - string toString() { - result = "Function" - } + FunctionParent getParent() { py_Functions(this, result) } + string toString() { result = "Function" } } library class FunctionExpr_ extends @py_FunctionExpr, Expr { - - /** Gets the name of this function definition. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the parameters of this function definition. */ - Arguments getArgs() { - py_arguments(result, this) - } - + Arguments getArgs() { py_arguments(result, this) } /** Gets the return annotation of this function definition. */ - Expr getReturns() { - py_exprs(result, _, this, 4) - } - + Expr getReturns() { py_exprs(result, _, this, 4) } /** Gets the function scope of this function definition. */ - Function getInnerScope() { - py_Functions(result, this) - } - - override string toString() { - result = "FunctionExpr" - } + Function getInnerScope() { py_Functions(result, this) } + override string toString() { result = "FunctionExpr" } } library class FunctionParent_ extends @py_Function_parent { - - string toString() { - result = "FunctionParent" - } - + string toString() { result = "FunctionParent" } } library class GeneratorExp_ extends @py_GeneratorExp, Expr { - - /** Gets the implementation of this generator expression. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this generator expression. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "GeneratorExp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "GeneratorExp" } } library class Global_ extends @py_Global, Stmt { - - /** Gets the names of this global statement. */ - StringList getNames() { - py_str_lists(result, this) - } - + StringList getNames() { py_str_lists(result, this) } /** Gets the nth name of this global statement. */ - string getName(int index) { - result = this.getNames().getItem(index) - } + string getName(int index) { result = this.getNames().getItem(index) } /** Gets a name of this global statement. */ - string getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Global" - } + string getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Global" } } library class Gt_ extends @py_Gt, Cmpop { - - override string toString() { - result = "Gt" - } - + override string toString() { result = "Gt" } } library class GtE_ extends @py_GtE, Cmpop { - - override string toString() { - result = "GtE" - } - + override string toString() { result = "GtE" } } library class If_ extends @py_If, Stmt { - - /** Gets the test of this if statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the if-true block of this if statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth if-true statement of this if statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets an if-true statement of this if statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the if-false block of this if statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 3) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 3) } /** Gets the nth if-false statement of this if statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an if-false statement of this if statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - - override string toString() { - result = "If" - } + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } + override string toString() { result = "If" } } library class IfExp_ extends @py_IfExp, Expr { - - /** Gets the test of this if expression. */ - Expr getTest() { - py_exprs(result, _, this, 2) - } - + Expr getTest() { py_exprs(result, _, this, 2) } /** Gets the if-true expression of this if expression. */ - Expr getBody() { - py_exprs(result, _, this, 3) - } - + Expr getBody() { py_exprs(result, _, this, 3) } /** Gets the if-false expression of this if expression. */ - Expr getOrelse() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "IfExp" - } + Expr getOrelse() { py_exprs(result, _, this, 4) } + override string toString() { result = "IfExp" } } library class Import_ extends @py_Import, Stmt { - - /** Gets the alias list of this import statement. */ - AliasList getNames() { - py_alias_lists(result, this) - } - + AliasList getNames() { py_alias_lists(result, this) } /** Gets the nth alias of this import statement. */ - Alias getName(int index) { - result = this.getNames().getItem(index) - } + Alias getName(int index) { result = this.getNames().getItem(index) } /** Gets an alias of this import statement. */ - Alias getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Import" - } + Alias getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Import" } } library class ImportExpr_ extends @py_ImportExpr, Expr { - - /** Gets the level of this import expression. */ - int getLevel() { - py_ints(result, this) - } - + int getLevel() { py_ints(result, this) } /** Gets the name of this import expression. */ - string getName() { - py_strs(result, this, 3) - } - + string getName() { py_strs(result, this, 3) } /** Whether the top level property of this import expression is true. */ - predicate isTop() { - py_bools(this, 4) - } - - override string toString() { - result = "ImportExpr" - } + predicate isTop() { py_bools(this, 4) } + override string toString() { result = "ImportExpr" } } library class ImportStar_ extends @py_ImportStar, Stmt { - - /** Gets the module of this import * statement. */ - Expr getModule() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "ImportStar" - } + Expr getModule() { py_exprs(result, _, this, 1) } + override string toString() { result = "ImportStar" } } library class ImportMember_ extends @py_ImportMember, Expr { - - /** Gets the module of this from import. */ - Expr getModule() { - py_exprs(result, _, this, 2) - } - + Expr getModule() { py_exprs(result, _, this, 2) } /** Gets the name of this from import. */ - string getName() { - py_strs(result, this, 3) - } - - override string toString() { - result = "ImportMember" - } + string getName() { py_strs(result, this, 3) } + override string toString() { result = "ImportMember" } } library class In_ extends @py_In, Cmpop { - - override string toString() { - result = "In" - } - + override string toString() { result = "In" } } library class Invert_ extends @py_Invert, Unaryop { - - override string toString() { - result = "Invert" - } - + override string toString() { result = "Invert" } } library class Is_ extends @py_Is, Cmpop { - - override string toString() { - result = "Is" - } - + override string toString() { result = "Is" } } library class IsNot_ extends @py_IsNot, Cmpop { - - override string toString() { - result = "IsNot" - } - + override string toString() { result = "IsNot" } } library class Fstring_ extends @py_Fstring, Expr { - - /** Gets the values of this formatted string literal. */ - ExprList getValues() { - py_expr_lists(result, this, 2) - } - + ExprList getValues() { py_expr_lists(result, this, 2) } /** Gets the nth value of this formatted string literal. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a value of this formatted string literal. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } + Expr getAValue() { result = this.getValues().getAnItem() } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Fstring" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Fstring" } } library class KeyValuePair_ extends @py_KeyValuePair, DictItem { - - /** Gets the location of this key-value pair. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this key-value pair. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the key of this key-value pair. */ - Expr getKey() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "KeyValuePair" - } + Expr getKey() { py_exprs(result, _, this, 2) } + override string toString() { result = "KeyValuePair" } } library class LShift_ extends @py_LShift, Operator { - - override string toString() { - result = "LShift" - } - + override string toString() { result = "LShift" } } library class Lambda_ extends @py_Lambda, Expr { - - /** Gets the arguments of this lambda expression. */ - Arguments getArgs() { - py_arguments(result, this) - } - + Arguments getArgs() { py_arguments(result, this) } /** Gets the function scope of this lambda expression. */ - Function getInnerScope() { - py_Functions(result, this) - } - - override string toString() { - result = "Lambda" - } + Function getInnerScope() { py_Functions(result, this) } + override string toString() { result = "Lambda" } } library class List_ extends @py_List, Expr { - - /** Gets the element list of this list expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this list expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this list expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - + Expr getAnElt() { result = this.getElts().getAnItem() } /** Gets the context of this list expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "List" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "List" } } library class ListComp_ extends @py_ListComp, Expr { - - /** Gets the implementation of this list comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this list comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - + Expr getIterable() { py_exprs(result, _, this, 3) } /** Gets the generators of this list comprehension. */ - ComprehensionList getGenerators() { - py_comprehension_lists(result, this) - } - + ComprehensionList getGenerators() { py_comprehension_lists(result, this) } /** Gets the nth generator of this list comprehension. */ - Comprehension getGenerator(int index) { - result = this.getGenerators().getItem(index) - } + Comprehension getGenerator(int index) { result = this.getGenerators().getItem(index) } /** Gets a generator of this list comprehension. */ - Comprehension getAGenerator() { - result = this.getGenerators().getAnItem() - } - + Comprehension getAGenerator() { result = this.getGenerators().getAnItem() } /** Gets the elements of this list comprehension. */ - Expr getElt() { - py_exprs(result, _, this, 5) - } - - override string toString() { - result = "ListComp" - } + Expr getElt() { py_exprs(result, _, this, 5) } + override string toString() { result = "ListComp" } } library class Load_ extends @py_Load, ExprContext { - - override string toString() { - result = "Load" - } - + override string toString() { result = "Load" } } library class Lt_ extends @py_Lt, Cmpop { - - override string toString() { - result = "Lt" - } - + override string toString() { result = "Lt" } } library class LtE_ extends @py_LtE, Cmpop { - - override string toString() { - result = "LtE" - } - + override string toString() { result = "LtE" } } library class MatMult_ extends @py_MatMult, Operator { - - override string toString() { - result = "MatMult" - } - + override string toString() { result = "MatMult" } } library class Mod_ extends @py_Mod, Operator { - - override string toString() { - result = "Mod" - } - + override string toString() { result = "Mod" } } library class Module_ extends @py_Module { - - /** Gets the name of this module. */ - string getName() { - py_strs(result, this, 0) - } - + string getName() { py_strs(result, this, 0) } /** Gets the hash (not populated) of this module. */ - string getHash() { - py_strs(result, this, 1) - } - + string getHash() { py_strs(result, this, 1) } /** Gets the body of this module. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth statement of this module. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this module. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the kind of this module. */ - string getKind() { - py_strs(result, this, 3) - } - - string toString() { - result = "Module" - } + string getKind() { py_strs(result, this, 3) } + string toString() { result = "Module" } } library class Mult_ extends @py_Mult, Operator { - - override string toString() { - result = "Mult" - } - + override string toString() { result = "Mult" } } library class Name_ extends @py_Name, Expr { - - /** Gets the variable of this name expression. */ - Variable getVariable() { - py_variables(result, this) - } - + Variable getVariable() { py_variables(result, this) } /** Gets the context of this name expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Name" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Name" } } library class Nonlocal_ extends @py_Nonlocal, Stmt { - - /** Gets the names of this nonlocal statement. */ - StringList getNames() { - py_str_lists(result, this) - } - + StringList getNames() { py_str_lists(result, this) } /** Gets the nth name of this nonlocal statement. */ - string getName(int index) { - result = this.getNames().getItem(index) - } + string getName(int index) { result = this.getNames().getItem(index) } /** Gets a name of this nonlocal statement. */ - string getAName() { - result = this.getNames().getAnItem() - } - - override string toString() { - result = "Nonlocal" - } + string getAName() { result = this.getNames().getAnItem() } + override string toString() { result = "Nonlocal" } } library class Not_ extends @py_Not, Unaryop { - - override string toString() { - result = "Not" - } - + override string toString() { result = "Not" } } library class NotEq_ extends @py_NotEq, Cmpop { - - override string toString() { - result = "NotEq" - } - + override string toString() { result = "NotEq" } } library class NotIn_ extends @py_NotIn, Cmpop { - - override string toString() { - result = "NotIn" - } - + override string toString() { result = "NotIn" } } library class Num_ extends @py_Num, Expr { - - /** Gets the value of this numeric literal. */ - string getN() { - py_numbers(result, this, 2) - } - + string getN() { py_numbers(result, this, 2) } /** Gets the text of this numeric literal. */ - string getText() { - py_numbers(result, this, 3) - } - - override string toString() { - result = "Num" - } + string getText() { py_numbers(result, this, 3) } + override string toString() { result = "Num" } } library class Or_ extends @py_Or, Boolop { - - override string toString() { - result = "Or" - } - + override string toString() { result = "Or" } } library class Param_ extends @py_Param, ExprContext { - - override string toString() { - result = "Param" - } - + override string toString() { result = "Param" } } library class Pass_ extends @py_Pass, Stmt { - - override string toString() { - result = "Pass" - } - + override string toString() { result = "Pass" } } library class PlaceHolder_ extends @py_PlaceHolder, Expr { - - /** Gets the variable of this template place-holder expression. */ - Variable getVariable() { - py_variables(result, this) - } - + Variable getVariable() { py_variables(result, this) } /** Gets the context of this template place-holder expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "PlaceHolder" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "PlaceHolder" } } library class Pow_ extends @py_Pow, Operator { - - override string toString() { - result = "Pow" - } - + override string toString() { result = "Pow" } } library class Print_ extends @py_Print, Stmt { - - /** Gets the destination of this print statement. */ - Expr getDest() { - py_exprs(result, _, this, 1) - } - + Expr getDest() { py_exprs(result, _, this, 1) } /** Gets the values of this print statement. */ - ExprList getValues() { - py_expr_lists(result, this, 2) - } - + ExprList getValues() { py_expr_lists(result, this, 2) } /** Gets the nth value of this print statement. */ - Expr getValue(int index) { - result = this.getValues().getItem(index) - } + Expr getValue(int index) { result = this.getValues().getItem(index) } /** Gets a value of this print statement. */ - Expr getAValue() { - result = this.getValues().getAnItem() - } - + Expr getAValue() { result = this.getValues().getAnItem() } /** Whether the new line property of this print statement is true. */ - predicate isNl() { - py_bools(this, 3) - } - - override string toString() { - result = "Print" - } + predicate isNl() { py_bools(this, 3) } + override string toString() { result = "Print" } } library class RShift_ extends @py_RShift, Operator { - - override string toString() { - result = "RShift" - } - + override string toString() { result = "RShift" } } library class Raise_ extends @py_Raise, Stmt { - - /** Gets the exception of this raise statement. */ - Expr getExc() { - py_exprs(result, _, this, 1) - } - + Expr getExc() { py_exprs(result, _, this, 1) } /** Gets the cause of this raise statement. */ - Expr getCause() { - py_exprs(result, _, this, 2) - } - + Expr getCause() { py_exprs(result, _, this, 2) } /** Gets the type of this raise statement. */ - Expr getType() { - py_exprs(result, _, this, 3) - } - + Expr getType() { py_exprs(result, _, this, 3) } /** Gets the instance of this raise statement. */ - Expr getInst() { - py_exprs(result, _, this, 4) - } - + Expr getInst() { py_exprs(result, _, this, 4) } /** Gets the traceback of this raise statement. */ - Expr getTback() { - py_exprs(result, _, this, 5) - } - - override string toString() { - result = "Raise" - } + Expr getTback() { py_exprs(result, _, this, 5) } + override string toString() { result = "Raise" } } library class Repr_ extends @py_Repr, Expr { - - /** Gets the value of this backtick expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Repr" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Repr" } } library class Return_ extends @py_Return, Stmt { - - /** Gets the value of this return statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "Return" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "Return" } } library class Set_ extends @py_Set, Expr { - - /** Gets the elements of this set expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this set expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this set expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - - override string toString() { - result = "Set" - } + Expr getAnElt() { result = this.getElts().getAnItem() } + override string toString() { result = "Set" } } library class SetComp_ extends @py_SetComp, Expr { - - /** Gets the implementation of this set comprehension. */ - Function getFunction() { - py_Functions(result, this) - } - + Function getFunction() { py_Functions(result, this) } /** Gets the iterable of this set comprehension. */ - Expr getIterable() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "SetComp" - } + Expr getIterable() { py_exprs(result, _, this, 3) } + override string toString() { result = "SetComp" } } library class Slice_ extends @py_Slice, Expr { - - /** Gets the start of this slice. */ - Expr getStart() { - py_exprs(result, _, this, 2) - } - + Expr getStart() { py_exprs(result, _, this, 2) } /** Gets the stop of this slice. */ - Expr getStop() { - py_exprs(result, _, this, 3) - } - + Expr getStop() { py_exprs(result, _, this, 3) } /** Gets the step of this slice. */ - Expr getStep() { - py_exprs(result, _, this, 4) - } - - override string toString() { - result = "Slice" - } + Expr getStep() { py_exprs(result, _, this, 4) } + override string toString() { result = "Slice" } } library class SpecialOperation_ extends @py_SpecialOperation, Expr { - - /** Gets the name of this special operation. */ - string getName() { - py_strs(result, this, 2) - } - + string getName() { py_strs(result, this, 2) } /** Gets the arguments of this special operation. */ - ExprList getArguments() { - py_expr_lists(result, this, 3) - } - + ExprList getArguments() { py_expr_lists(result, this, 3) } /** Gets the nth argument of this special operation. */ - Expr getArgument(int index) { - result = this.getArguments().getItem(index) - } + Expr getArgument(int index) { result = this.getArguments().getItem(index) } /** Gets an argument of this special operation. */ - Expr getAnArgument() { - result = this.getArguments().getAnItem() - } - - override string toString() { - result = "SpecialOperation" - } + Expr getAnArgument() { result = this.getArguments().getAnItem() } + override string toString() { result = "SpecialOperation" } } library class Starred_ extends @py_Starred, Expr { - - /** Gets the value of this starred expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the context of this starred expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Starred" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Starred" } } library class Store_ extends @py_Store, ExprContext { - - override string toString() { - result = "Store" - } - + override string toString() { result = "Store" } } library class Str_ extends @py_Str, Expr { - - /** Gets the text of this string literal. */ - string getS() { - py_strs(result, this, 2) - } - + string getS() { py_strs(result, this, 2) } /** Gets the prefix of this string literal. */ - string getPrefix() { - py_strs(result, this, 3) - } - + string getPrefix() { py_strs(result, this, 3) } /** Gets the implicitly_concatenated_parts of this string literal. */ - StringPartList getImplicitlyConcatenatedParts() { - py_StringPart_lists(result, this) - } - + StringPartList getImplicitlyConcatenatedParts() { py_StringPart_lists(result, this) } /** Gets the nth implicitly_concatenated_part of this string literal. */ StringPart getImplicitlyConcatenatedPart(int index) { @@ -1876,972 +965,501 @@ library class Str_ extends @py_Str, Expr { result = this.getImplicitlyConcatenatedParts().getAnItem() } - override string toString() { - result = "Str" - } - + override string toString() { result = "Str" } } library class StringPart_ extends @py_StringPart { - - /** Gets the text of this implicitly concatenated part. */ - string getText() { - py_strs(result, this, 0) - } - + string getText() { py_strs(result, this, 0) } /** Gets the location of this implicitly concatenated part. */ - Location getLocation() { - py_locations(result, this) - } + Location getLocation() { py_locations(result, this) } - StringPartList getParent() { - py_StringParts(this, result, _) - } - - string toString() { - result = "StringPart" - } + StringPartList getParent() { py_StringParts(this, result, _) } + string toString() { result = "StringPart" } } library class StringPartList_ extends @py_StringPart_list { - - BytesOrStr getParent() { - py_StringPart_lists(this, result) - } + BytesOrStr getParent() { py_StringPart_lists(this, result) } /** Gets an item of this implicitly concatenated part list */ - StringPart getAnItem() { - py_StringParts(result, this, _) - } + StringPart getAnItem() { py_StringParts(result, this, _) } /** Gets the nth item of this implicitly concatenated part list */ - StringPart getItem(int index) { - py_StringParts(result, this, index) - } - - string toString() { - result = "StringPartList" - } + StringPart getItem(int index) { py_StringParts(result, this, index) } + string toString() { result = "StringPartList" } } library class Sub_ extends @py_Sub, Operator { - - override string toString() { - result = "Sub" - } - + override string toString() { result = "Sub" } } library class Subscript_ extends @py_Subscript, Expr { - - /** Gets the value of this subscript expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the index of this subscript expression. */ - Expr getIndex() { - py_exprs(result, _, this, 3) - } - + Expr getIndex() { py_exprs(result, _, this, 3) } /** Gets the context of this subscript expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "Subscript" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "Subscript" } } library class TemplateDottedNotation_ extends @py_TemplateDottedNotation, Expr { - - /** Gets the object of this template dotted notation expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - + Expr getValue() { py_exprs(result, _, this, 2) } /** Gets the attribute name of this template dotted notation expression. */ - string getAttr() { - py_strs(result, this, 3) - } - + string getAttr() { py_strs(result, this, 3) } /** Gets the context of this template dotted notation expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } - - override string toString() { - result = "TemplateDottedNotation" - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } + override string toString() { result = "TemplateDottedNotation" } } library class TemplateWrite_ extends @py_TemplateWrite, Stmt { - - /** Gets the value of this template write statement. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - - override string toString() { - result = "TemplateWrite" - } + Expr getValue() { py_exprs(result, _, this, 1) } + override string toString() { result = "TemplateWrite" } } library class Try_ extends @py_Try, Stmt { - - /** Gets the body of this try statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 1) - } - + StmtList getBody() { py_stmt_lists(result, this, 1) } /** Gets the nth statement of this try statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this try statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this try statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 2) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 2) } /** Gets the nth else statement of this try statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this try statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } /** Gets the exception handlers of this try statement. */ - StmtList getHandlers() { - py_stmt_lists(result, this, 3) - } - + StmtList getHandlers() { py_stmt_lists(result, this, 3) } /** Gets the nth exception handler of this try statement. */ - Stmt getHandler(int index) { - result = this.getHandlers().getItem(index) - } + Stmt getHandler(int index) { result = this.getHandlers().getItem(index) } /** Gets an exception handler of this try statement. */ - Stmt getAHandler() { - result = this.getHandlers().getAnItem() - } - + Stmt getAHandler() { result = this.getHandlers().getAnItem() } /** Gets the finally block of this try statement. */ - StmtList getFinalbody() { - py_stmt_lists(result, this, 4) - } - + StmtList getFinalbody() { py_stmt_lists(result, this, 4) } /** Gets the nth finally statement of this try statement. */ - Stmt getFinalstmt(int index) { - result = this.getFinalbody().getItem(index) - } + Stmt getFinalstmt(int index) { result = this.getFinalbody().getItem(index) } /** Gets a finally statement of this try statement. */ - Stmt getAFinalstmt() { - result = this.getFinalbody().getAnItem() - } - - override string toString() { - result = "Try" - } + Stmt getAFinalstmt() { result = this.getFinalbody().getAnItem() } + override string toString() { result = "Try" } } library class Tuple_ extends @py_Tuple, Expr { - - /** Gets the elements of this tuple expression. */ - ExprList getElts() { - py_expr_lists(result, this, 2) - } - + ExprList getElts() { py_expr_lists(result, this, 2) } /** Gets the nth element of this tuple expression. */ - Expr getElt(int index) { - result = this.getElts().getItem(index) - } + Expr getElt(int index) { result = this.getElts().getItem(index) } /** Gets an element of this tuple expression. */ - Expr getAnElt() { - result = this.getElts().getAnItem() - } - + Expr getAnElt() { result = this.getElts().getAnItem() } /** Gets the context of this tuple expression. */ - ExprContext getCtx() { - py_expr_contexts(result, _, this) - } + ExprContext getCtx() { py_expr_contexts(result, _, this) } - override ExprParent getParent() { - py_exprs(this, _, result, _) - } - - override string toString() { - result = "Tuple" - } + override ExprParent getParent() { py_exprs(this, _, result, _) } + override string toString() { result = "Tuple" } } library class UAdd_ extends @py_UAdd, Unaryop { - - override string toString() { - result = "UAdd" - } - + override string toString() { result = "UAdd" } } library class USub_ extends @py_USub, Unaryop { - - override string toString() { - result = "USub" - } - + override string toString() { result = "USub" } } library class UnaryExpr_ extends @py_UnaryExpr, Expr { - - /** Gets the operator of this unary expression. */ - Unaryop getOp() { - py_unaryops(result, _, this) - } - + Unaryop getOp() { py_unaryops(result, _, this) } /** Gets the operand of this unary expression. */ - Expr getOperand() { - py_exprs(result, _, this, 3) - } - - override string toString() { - result = "UnaryExpr" - } + Expr getOperand() { py_exprs(result, _, this, 3) } + override string toString() { result = "UnaryExpr" } } library class While_ extends @py_While, Stmt { - - /** Gets the test of this while statement. */ - Expr getTest() { - py_exprs(result, _, this, 1) - } - + Expr getTest() { py_exprs(result, _, this, 1) } /** Gets the body of this while statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 2) - } - + StmtList getBody() { py_stmt_lists(result, this, 2) } /** Gets the nth statement of this while statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this while statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Gets the else block of this while statement. */ - StmtList getOrelse() { - py_stmt_lists(result, this, 3) - } - + StmtList getOrelse() { py_stmt_lists(result, this, 3) } /** Gets the nth else statement of this while statement. */ - Stmt getOrelse(int index) { - result = this.getOrelse().getItem(index) - } + Stmt getOrelse(int index) { result = this.getOrelse().getItem(index) } /** Gets an else statement of this while statement. */ - Stmt getAnOrelse() { - result = this.getOrelse().getAnItem() - } - - override string toString() { - result = "While" - } + Stmt getAnOrelse() { result = this.getOrelse().getAnItem() } + override string toString() { result = "While" } } library class With_ extends @py_With, Stmt { - - /** Gets the context manager of this with statement. */ - Expr getContextExpr() { - py_exprs(result, _, this, 1) - } - + Expr getContextExpr() { py_exprs(result, _, this, 1) } /** Gets the optional variable of this with statement. */ - Expr getOptionalVars() { - py_exprs(result, _, this, 2) - } - + Expr getOptionalVars() { py_exprs(result, _, this, 2) } /** Gets the body of this with statement. */ - StmtList getBody() { - py_stmt_lists(result, this, 3) - } - + StmtList getBody() { py_stmt_lists(result, this, 3) } /** Gets the nth statement of this with statement. */ - Stmt getStmt(int index) { - result = this.getBody().getItem(index) - } + Stmt getStmt(int index) { result = this.getBody().getItem(index) } /** Gets a statement of this with statement. */ - Stmt getAStmt() { - result = this.getBody().getAnItem() - } - + Stmt getAStmt() { result = this.getBody().getAnItem() } /** Whether the async property of this with statement is true. */ - predicate isAsync() { - py_bools(this, 4) - } - - override string toString() { - result = "With" - } + predicate isAsync() { py_bools(this, 4) } + override string toString() { result = "With" } } library class Yield_ extends @py_Yield, Expr { - - /** Gets the value of this yield expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "Yield" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "Yield" } } library class YieldFrom_ extends @py_YieldFrom, Expr { - - /** Gets the value of this yield-from expression. */ - Expr getValue() { - py_exprs(result, _, this, 2) - } - - override string toString() { - result = "YieldFrom" - } + Expr getValue() { py_exprs(result, _, this, 2) } + override string toString() { result = "YieldFrom" } } library class Alias_ extends @py_alias { - - /** Gets the value of this alias. */ - Expr getValue() { - py_exprs(result, _, this, 0) - } - + Expr getValue() { py_exprs(result, _, this, 0) } /** Gets the name of this alias. */ - Expr getAsname() { - py_exprs(result, _, this, 1) - } + Expr getAsname() { py_exprs(result, _, this, 1) } - AliasList getParent() { - py_aliases(this, result, _) - } - - string toString() { - result = "Alias" - } + AliasList getParent() { py_aliases(this, result, _) } + string toString() { result = "Alias" } } library class AliasList_ extends @py_alias_list { - - Import getParent() { - py_alias_lists(this, result) - } + Import getParent() { py_alias_lists(this, result) } /** Gets an item of this alias list */ - Alias getAnItem() { - py_aliases(result, this, _) - } + Alias getAnItem() { py_aliases(result, this, _) } /** Gets the nth item of this alias list */ - Alias getItem(int index) { - py_aliases(result, this, index) - } - - string toString() { - result = "AliasList" - } + Alias getItem(int index) { py_aliases(result, this, index) } + string toString() { result = "AliasList" } } library class Arguments_ extends @py_arguments { - - /** Gets the keyword default values of this parameters definition. */ - ExprList getKwDefaults() { - py_expr_lists(result, this, 0) - } - + ExprList getKwDefaults() { py_expr_lists(result, this, 0) } /** Gets the nth keyword default value of this parameters definition. */ - Expr getKwDefault(int index) { - result = this.getKwDefaults().getItem(index) - } + Expr getKwDefault(int index) { result = this.getKwDefaults().getItem(index) } /** Gets a keyword default value of this parameters definition. */ - Expr getAKwDefault() { - result = this.getKwDefaults().getAnItem() - } - + Expr getAKwDefault() { result = this.getKwDefaults().getAnItem() } /** Gets the default values of this parameters definition. */ - ExprList getDefaults() { - py_expr_lists(result, this, 1) - } - + ExprList getDefaults() { py_expr_lists(result, this, 1) } /** Gets the nth default value of this parameters definition. */ - Expr getDefault(int index) { - result = this.getDefaults().getItem(index) - } + Expr getDefault(int index) { result = this.getDefaults().getItem(index) } /** Gets a default value of this parameters definition. */ - Expr getADefault() { - result = this.getDefaults().getAnItem() - } - + Expr getADefault() { result = this.getDefaults().getAnItem() } /** Gets the annotations of this parameters definition. */ - ExprList getAnnotations() { - py_expr_lists(result, this, 2) - } - + ExprList getAnnotations() { py_expr_lists(result, this, 2) } /** Gets the nth annotation of this parameters definition. */ - Expr getAnnotation(int index) { - result = this.getAnnotations().getItem(index) - } + Expr getAnnotation(int index) { result = this.getAnnotations().getItem(index) } /** Gets an annotation of this parameters definition. */ - Expr getAnAnnotation() { - result = this.getAnnotations().getAnItem() - } - + Expr getAnAnnotation() { result = this.getAnnotations().getAnItem() } /** Gets the *arg annotation of this parameters definition. */ - Expr getVarargannotation() { - py_exprs(result, _, this, 3) - } - + Expr getVarargannotation() { py_exprs(result, _, this, 3) } /** Gets the **kwarg annotation of this parameters definition. */ - Expr getKwargannotation() { - py_exprs(result, _, this, 4) - } - + Expr getKwargannotation() { py_exprs(result, _, this, 4) } /** Gets the kw_annotations of this parameters definition. */ - ExprList getKwAnnotations() { - py_expr_lists(result, this, 5) - } - + ExprList getKwAnnotations() { py_expr_lists(result, this, 5) } /** Gets the nth kw_annotation of this parameters definition. */ - Expr getKwAnnotation(int index) { - result = this.getKwAnnotations().getItem(index) - } + Expr getKwAnnotation(int index) { result = this.getKwAnnotations().getItem(index) } /** Gets a kw_annotation of this parameters definition. */ - Expr getAKwAnnotation() { - result = this.getKwAnnotations().getAnItem() - } + Expr getAKwAnnotation() { result = this.getKwAnnotations().getAnItem() } - ArgumentsParent getParent() { - py_arguments(this, result) - } - - string toString() { - result = "Arguments" - } + ArgumentsParent getParent() { py_arguments(this, result) } + string toString() { result = "Arguments" } } library class ArgumentsParent_ extends @py_arguments_parent { - - string toString() { - result = "ArgumentsParent" - } - + string toString() { result = "ArgumentsParent" } } library class AstNode_ extends @py_ast_node { - - string toString() { - result = "AstNode" - } - + string toString() { result = "AstNode" } } library class BoolParent_ extends @py_bool_parent { - - string toString() { - result = "BoolParent" - } - + string toString() { result = "BoolParent" } } library class Boolop_ extends @py_boolop { + BoolExpr getParent() { py_boolops(this, _, result) } - BoolExpr getParent() { - py_boolops(this, _, result) - } - - string toString() { - result = "Boolop" - } - + string toString() { result = "Boolop" } } library class Cmpop_ extends @py_cmpop { + CmpopList getParent() { py_cmpops(this, _, result, _) } - CmpopList getParent() { - py_cmpops(this, _, result, _) - } - - string toString() { - result = "Cmpop" - } - + string toString() { result = "Cmpop" } } library class CmpopList_ extends @py_cmpop_list { - - Compare getParent() { - py_cmpop_lists(this, result) - } + Compare getParent() { py_cmpop_lists(this, result) } /** Gets an item of this comparison operator list */ - Cmpop getAnItem() { - py_cmpops(result, _, this, _) - } + Cmpop getAnItem() { py_cmpops(result, _, this, _) } /** Gets the nth item of this comparison operator list */ - Cmpop getItem(int index) { - py_cmpops(result, _, this, index) - } - - string toString() { - result = "CmpopList" - } + Cmpop getItem(int index) { py_cmpops(result, _, this, index) } + string toString() { result = "CmpopList" } } library class Comprehension_ extends @py_comprehension { - - /** Gets the location of this comprehension. */ - Location getLocation() { - py_locations(result, this) - } - + Location getLocation() { py_locations(result, this) } /** Gets the iterable of this comprehension. */ - Expr getIter() { - py_exprs(result, _, this, 1) - } - + Expr getIter() { py_exprs(result, _, this, 1) } /** Gets the target of this comprehension. */ - Expr getTarget() { - py_exprs(result, _, this, 2) - } - + Expr getTarget() { py_exprs(result, _, this, 2) } /** Gets the conditions of this comprehension. */ - ExprList getIfs() { - py_expr_lists(result, this, 3) - } - + ExprList getIfs() { py_expr_lists(result, this, 3) } /** Gets the nth condition of this comprehension. */ - Expr getIf(int index) { - result = this.getIfs().getItem(index) - } + Expr getIf(int index) { result = this.getIfs().getItem(index) } /** Gets a condition of this comprehension. */ - Expr getAnIf() { - result = this.getIfs().getAnItem() - } + Expr getAnIf() { result = this.getIfs().getAnItem() } - ComprehensionList getParent() { - py_comprehensions(this, result, _) - } - - string toString() { - result = "Comprehension" - } + ComprehensionList getParent() { py_comprehensions(this, result, _) } + string toString() { result = "Comprehension" } } library class ComprehensionList_ extends @py_comprehension_list { - - ListComp getParent() { - py_comprehension_lists(this, result) - } + ListComp getParent() { py_comprehension_lists(this, result) } /** Gets an item of this comprehension list */ - Comprehension getAnItem() { - py_comprehensions(result, this, _) - } + Comprehension getAnItem() { py_comprehensions(result, this, _) } /** Gets the nth item of this comprehension list */ - Comprehension getItem(int index) { - py_comprehensions(result, this, index) - } - - string toString() { - result = "ComprehensionList" - } + Comprehension getItem(int index) { py_comprehensions(result, this, index) } + string toString() { result = "ComprehensionList" } } library class DictItem_ extends @py_dict_item { + DictItemList getParent() { py_dict_items(this, _, result, _) } - DictItemList getParent() { - py_dict_items(this, _, result, _) - } - - string toString() { - result = "DictItem" - } - + string toString() { result = "DictItem" } } library class DictItemList_ extends @py_dict_item_list { - - DictItemListParent getParent() { - py_dict_item_lists(this, result) - } + DictItemListParent getParent() { py_dict_item_lists(this, result) } /** Gets an item of this dict_item list */ - DictItem getAnItem() { - py_dict_items(result, _, this, _) - } + DictItem getAnItem() { py_dict_items(result, _, this, _) } /** Gets the nth item of this dict_item list */ - DictItem getItem(int index) { - py_dict_items(result, _, this, index) - } - - string toString() { - result = "DictItemList" - } + DictItem getItem(int index) { py_dict_items(result, _, this, index) } + string toString() { result = "DictItemList" } } library class DictItemListParent_ extends @py_dict_item_list_parent { - - string toString() { - result = "DictItemListParent" - } - + string toString() { result = "DictItemListParent" } } library class Expr_ extends @py_expr { - - /** Gets the location of this expression. */ - Location getLocation() { - py_locations(result, this) - } - + Location getLocation() { py_locations(result, this) } /** Whether the parenthesised property of this expression is true. */ - predicate isParenthesised() { - py_bools(this, 1) - } + predicate isParenthesised() { py_bools(this, 1) } - ExprParent getParent() { - py_exprs(this, _, result, _) - } - - string toString() { - result = "Expr" - } + ExprParent getParent() { py_exprs(this, _, result, _) } + string toString() { result = "Expr" } } library class ExprContext_ extends @py_expr_context { + ExprContextParent getParent() { py_expr_contexts(this, _, result) } - ExprContextParent getParent() { - py_expr_contexts(this, _, result) - } - - string toString() { - result = "ExprContext" - } - + string toString() { result = "ExprContext" } } library class ExprContextParent_ extends @py_expr_context_parent { - - string toString() { - result = "ExprContextParent" - } - + string toString() { result = "ExprContextParent" } } library class ExprList_ extends @py_expr_list { - - ExprListParent getParent() { - py_expr_lists(this, result, _) - } + ExprListParent getParent() { py_expr_lists(this, result, _) } /** Gets an item of this expression list */ - Expr getAnItem() { - py_exprs(result, _, this, _) - } + Expr getAnItem() { py_exprs(result, _, this, _) } /** Gets the nth item of this expression list */ - Expr getItem(int index) { - py_exprs(result, _, this, index) - } - - string toString() { - result = "ExprList" - } + Expr getItem(int index) { py_exprs(result, _, this, index) } + string toString() { result = "ExprList" } } library class ExprListParent_ extends @py_expr_list_parent { - - string toString() { - result = "ExprListParent" - } - + string toString() { result = "ExprListParent" } } library class ExprOrStmt_ extends @py_expr_or_stmt { - - string toString() { - result = "ExprOrStmt" - } - + string toString() { result = "ExprOrStmt" } } library class ExprParent_ extends @py_expr_parent { - - string toString() { - result = "ExprParent" - } - + string toString() { result = "ExprParent" } } library class Keyword_ extends @py_keyword, DictItem { - - /** Gets the location of this keyword argument. */ - override Location getLocation() { - py_locations(result, this) - } - + override Location getLocation() { py_locations(result, this) } /** Gets the value of this keyword argument. */ - Expr getValue() { - py_exprs(result, _, this, 1) - } - + Expr getValue() { py_exprs(result, _, this, 1) } /** Gets the arg of this keyword argument. */ - string getArg() { - py_strs(result, this, 2) - } - - override string toString() { - result = "Keyword" - } + string getArg() { py_strs(result, this, 2) } + override string toString() { result = "Keyword" } } library class LocationParent_ extends @py_location_parent { - - string toString() { - result = "LocationParent" - } - + string toString() { result = "LocationParent" } } library class Operator_ extends @py_operator { + BinaryExpr getParent() { py_operators(this, _, result) } - BinaryExpr getParent() { - py_operators(this, _, result) - } - - string toString() { - result = "Operator" - } - + string toString() { result = "Operator" } } library class Parameter_ extends @py_parameter { - - string toString() { - result = "Parameter" - } - + string toString() { result = "Parameter" } } library class Scope_ extends @py_scope { - - string toString() { - result = "Scope" - } - + string toString() { result = "Scope" } } library class Stmt_ extends @py_stmt { - - /** Gets the location of this statement. */ - Location getLocation() { - py_locations(result, this) - } + Location getLocation() { py_locations(result, this) } - StmtList getParent() { - py_stmts(this, _, result, _) - } - - string toString() { - result = "Stmt" - } + StmtList getParent() { py_stmts(this, _, result, _) } + string toString() { result = "Stmt" } } library class StmtList_ extends @py_stmt_list { - - StmtListParent getParent() { - py_stmt_lists(this, result, _) - } + StmtListParent getParent() { py_stmt_lists(this, result, _) } /** Gets an item of this statement list */ - Stmt getAnItem() { - py_stmts(result, _, this, _) - } + Stmt getAnItem() { py_stmts(result, _, this, _) } /** Gets the nth item of this statement list */ - Stmt getItem(int index) { - py_stmts(result, _, this, index) - } - - string toString() { - result = "StmtList" - } + Stmt getItem(int index) { py_stmts(result, _, this, index) } + string toString() { result = "StmtList" } } library class StmtListParent_ extends @py_stmt_list_parent { - - string toString() { - result = "StmtListParent" - } - + string toString() { result = "StmtListParent" } } library class StringList_ extends @py_str_list { - - StrListParent getParent() { - py_str_lists(this, result) - } + StrListParent getParent() { py_str_lists(this, result) } /** Gets an item of this string list */ - string getAnItem() { - py_strs(result, this, _) - } + string getAnItem() { py_strs(result, this, _) } /** Gets the nth item of this string list */ - string getItem(int index) { - py_strs(result, this, index) - } - - string toString() { - result = "StringList" - } + string getItem(int index) { py_strs(result, this, index) } + string toString() { result = "StringList" } } library class StrListParent_ extends @py_str_list_parent { - - string toString() { - result = "StrListParent" - } - + string toString() { result = "StrListParent" } } library class StrParent_ extends @py_str_parent { - - string toString() { - result = "StrParent" - } - + string toString() { result = "StrParent" } } library class Unaryop_ extends @py_unaryop { + UnaryExpr getParent() { py_unaryops(this, _, result) } - UnaryExpr getParent() { - py_unaryops(this, _, result) - } - - string toString() { - result = "Unaryop" - } - + string toString() { result = "Unaryop" } } library class VariableParent_ extends @py_variable_parent { - - string toString() { - result = "VariableParent" - } - + string toString() { result = "VariableParent" } } - diff --git a/python/ql/src/semmle/python/Class.qll b/python/ql/src/semmle/python/Class.qll index 9cef58d4d81..daa68dcef4b 100644 --- a/python/ql/src/semmle/python/Class.qll +++ b/python/ql/src/semmle/python/Class.qll @@ -1,35 +1,40 @@ import python - -/** An (artificial) expression corresponding to a class definition. +/** + * An (artificial) expression corresponding to a class definition. * It is recommended to use `ClassDef` instead. */ class ClassExpr extends ClassExpr_ { - /** Gets the metaclass expression */ - Expr getMetaClass() { - if major_version() = 3 then - exists(Keyword metacls | this.getAKeyword() = metacls and metacls.getArg() = "metaclass" and result = metacls.getValue()) + Expr getMetaClass() { + if major_version() = 3 + then + exists(Keyword metacls | + this.getAKeyword() = metacls and + metacls.getArg() = "metaclass" and + result = metacls.getValue() + ) else - exists(Assign a | a = this.getInnerScope().getAStmt() and ((Name)a.getATarget()).getId() = "__metaclass__" and result = a.getValue()) + exists(Assign a | + a = this.getInnerScope().getAStmt() and + a.getATarget().(Name).getId() = "__metaclass__" and + result = a.getValue() + ) } - /** Gets the nth keyword argument of this class definition. */ override DictUnpackingOrKeyword getKeyword(int index) { result = this.getKeywords().getItem(index) } /** Gets a keyword argument of this class definition. */ - override DictUnpackingOrKeyword getAKeyword() { - result = this.getKeywords().getAnItem() - } + override DictUnpackingOrKeyword getAKeyword() { result = this.getKeywords().getAnItem() } override Expr getASubExpression() { - result = this.getABase() or - result = this.getAKeyword().getValue() or - result = this.getKwargs() or - result = this.getStarargs() + result = this.getABase() or + result = this.getAKeyword().getValue() or + result = this.getKwargs() or + result = this.getStarargs() } Call getADecoratorCall() { @@ -38,9 +43,7 @@ class ClassExpr extends ClassExpr_ { } /** Gets a decorator of this function expression */ - Expr getADecorator() { - result = this.getADecoratorCall().getFunc() - } + Expr getADecorator() { result = this.getADecoratorCall().getFunc() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -49,151 +52,102 @@ class ClassExpr extends ClassExpr_ { } /** Gets a tuple (*) argument of this class definition. */ - Expr getStarargs() { - result = this.getABase().(Starred).getValue() - } + Expr getStarargs() { result = this.getABase().(Starred).getValue() } /** Gets a dictionary (**) argument of this class definition. */ - Expr getKwargs() { - result = this.getAKeyword().(DictUnpacking).getValue() - } - + Expr getKwargs() { result = this.getAKeyword().(DictUnpacking).getValue() } } /** A class statement. Note that ClassDef extends Assign as a class definition binds the newly created class */ class ClassDef extends Assign { - /* syntax: class name(...): ... */ - ClassDef() { /* This is an artificial assignment the rhs of which is a (possibly decorated) ClassExpr */ exists(ClassExpr c | this.getValue() = c or this.getValue() = c.getADecoratorCall()) } - override string toString() { - result = "ClassDef" - } + override string toString() { result = "ClassDef" } /** Gets the class for this statement */ Class getDefinedClass() { - exists(ClassExpr c | - this.getValue() = c or this.getValue() = c.getADecoratorCall() | + exists(ClassExpr c | this.getValue() = c or this.getValue() = c.getADecoratorCall() | result = c.getInnerScope() ) } - override Stmt getLastStatement() { - result = this.getDefinedClass().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getDefinedClass().getLastStatement() } } /** The scope of a class. This is the scope of all the statements within the class definition */ class Class extends Class_, Scope, AstNode { - - /** Use getADecorator() instead of getDefinition().getADecorator() + /** + * Use getADecorator() instead of getDefinition().getADecorator() * Use getMetaClass() instead of getDefinition().getMetaClass() */ - deprecated ClassExpr getDefinition() { - result = this.getParent() - } + deprecated ClassExpr getDefinition() { result = this.getParent() } /** Gets a defined init method of this class */ - Function getInitMethod() { - result.getScope() = this and result.isInitMethod() - } + Function getInitMethod() { result.getScope() = this and result.isInitMethod() } /** Gets a method defined in this class */ - Function getAMethod() { - result.getScope() = this - } + Function getAMethod() { result.getScope() = this } - override Location getLocation() { - py_scope_location(result, this) - } + override Location getLocation() { py_scope_location(result, this) } /** Gets the scope (module, class or function) in which this class is defined */ - override Scope getEnclosingScope() { - result = this.getParent().getScope() - } + override Scope getEnclosingScope() { result = this.getParent().getScope() } /** Use getEnclosingScope() instead */ - override Scope getScope() { - result = this.getParent().getScope() - } + override Scope getScope() { result = this.getParent().getScope() } - override string toString() { - result = "Class " + this.getName() - } + override string toString() { result = "Class " + this.getName() } /** Gets the statements forming the body of this class */ - override StmtList getBody() { - result = Class_.super.getBody() - } + override StmtList getBody() { result = Class_.super.getBody() } /** Gets the nth statement in the class */ - override Stmt getStmt(int index) { - result = Class_.super.getStmt(index) - } + override Stmt getStmt(int index) { result = Class_.super.getStmt(index) } /** Gets a statement in the class */ - override Stmt getAStmt() { - result = Class_.super.getAStmt() - } + override Stmt getAStmt() { result = Class_.super.getAStmt() } /** Gets the name used to define this class */ - override string getName() { - result = Class_.super.getName() - } + override string getName() { result = Class_.super.getName() } - predicate hasSideEffects() { - any() - } + predicate hasSideEffects() { any() } /** Whether this is probably a mixin (has 'mixin' or similar in name or docstring) */ predicate isProbableMixin() { - (this.getName().toLowerCase().matches("%mixin%") - or - this.getDocString().getText().toLowerCase().matches("%mixin%") - or - this.getDocString().getText().toLowerCase().matches("%mix-in%") + ( + this.getName().toLowerCase().matches("%mixin%") + or + this.getDocString().getText().toLowerCase().matches("%mixin%") + or + this.getDocString().getText().toLowerCase().matches("%mix-in%") ) } - override AstNode getAChildNode() { - result = this.getAStmt() - } + override AstNode getAChildNode() { result = this.getAStmt() } - Expr getADecorator() { - result = this.getParent().getADecorator() - } + Expr getADecorator() { result = this.getParent().getADecorator() } /** Gets the metaclass expression */ - Expr getMetaClass() { - result = this.getParent().getMetaClass() - } + Expr getMetaClass() { result = this.getParent().getMetaClass() } /** Gets the ClassObject corresponding to this class */ - ClassObject getClassObject() { - result.getOrigin() = this.getParent() - } + ClassObject getClassObject() { result.getOrigin() = this.getParent() } /** Gets the nth base of this class definition. */ - Expr getBase(int index) { - result = this.getParent().getBase(index) - } + Expr getBase(int index) { result = this.getParent().getBase(index) } /** Gets a base of this class definition. */ - Expr getABase() { - result = this.getParent().getABase() - } + Expr getABase() { result = this.getParent().getABase() } /** Gets the metrics for this class */ - ClassMetrics getMetrics() { - result = this - } + ClassMetrics getMetrics() { result = this } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -202,20 +156,13 @@ class Class extends Class_, Scope, AstNode { exists(string enclosing_name | enclosing_name = this.getScope().(Function).getQualifiedName() or - enclosing_name = this.getScope().(Class).getQualifiedName() | + enclosing_name = this.getScope().(Class).getQualifiedName() + | result = enclosing_name + "." + this.getName() ) } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } - - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } } - diff --git a/python/ql/src/semmle/python/Comment.qll b/python/ql/src/semmle/python/Comment.qll index c40de34478b..e0b33c1c94b 100644 --- a/python/ql/src/semmle/python/Comment.qll +++ b/python/ql/src/semmle/python/Comment.qll @@ -2,38 +2,28 @@ import python /** A source code comment */ class Comment extends @py_comment { - /** Gets the full text of the comment including the leading '#' */ - string getText() { - py_comments(this, result, _) - } + string getText() { py_comments(this, result, _) } /** Gets the contents of the comment excluding the leading '#' */ - string getContents() { - result = this.getText().suffix(1) - } + string getContents() { result = this.getText().suffix(1) } - Location getLocation() { - py_comments(this, _, result) + Location getLocation() { py_comments(this, _, result) } - } + string toString() { result = "Comment " + this.getText() } - string toString() { - result = "Comment " + this.getText() - } - - /** Gets this immediately following comment. + /** + * Gets this immediately following comment. * Blanks line are allowed between this comment and the following comment, * but code or other comments are not. */ Comment getFollowing() { - exists(File f, int n | - this.file_line(f, n) | - result.file_line(f, n+1) + exists(File f, int n | this.file_line(f, n) | + result.file_line(f, n + 1) or - result.file_line(f, n+2) and f.emptyLine(n+1) + result.file_line(f, n + 2) and f.emptyLine(n + 1) or - result.file_line(f, n+3) and f.emptyLine(n+2) and f.emptyLine(n+1) + result.file_line(f, n + 3) and f.emptyLine(n + 2) and f.emptyLine(n + 1) ) } @@ -41,47 +31,34 @@ class Comment extends @py_comment { this.getLocation().getFile() = f and this.getLocation().getStartLine() = n } - } private predicate comment_block_part(Comment start, Comment part, int i) { not exists(Comment prev | prev.getFollowing() = part) and exists(Comment following | part.getFollowing() = following) and - start = part and i = 1 + start = part and + i = 1 or exists(Comment prev | - comment_block_part(start, prev, i-1) and + comment_block_part(start, prev, i - 1) and part = prev.getFollowing() ) } /** A block of consecutive comments */ class CommentBlock extends @py_comment { + CommentBlock() { comment_block_part(this, _, _) } - CommentBlock() { - comment_block_part(this, _, _) - } + private Comment last() { comment_block_part(this, result, this.length()) } - private Comment last() { - comment_block_part(this, result, this.length()) - } - - string toString() { - result = "Comment block" - } + string toString() { result = "Comment block" } /** The length of this comment block (in comments) */ - int length() { - result = max(int i | comment_block_part(this, _, i)) - } + int length() { result = max(int i | comment_block_part(this, _, i)) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - ((Comment)this).getLocation().hasLocationInfo(filepath, bl, bc, _, _) - and - exists(Comment end | - end = this.last() | - end.getLocation().hasLocationInfo(_, _, _, el, ec) - ) + this.(Comment).getLocation().hasLocationInfo(filepath, bl, bc, _, _) and + exists(Comment end | end = this.last() | end.getLocation().hasLocationInfo(_, _, _, el, ec)) } predicate contains(Comment c) { @@ -91,20 +68,18 @@ class CommentBlock extends @py_comment { } string getContents() { - result = concat(Comment c,int i | - comment_block_part(this, c, i) or this = c and i = 0 | - c.getContents() order by i - ) + result = + concat(Comment c, int i | + comment_block_part(this, c, i) + or + this = c and i = 0 + | + c.getContents() order by i + ) } - } /** A type-hint comment. Any comment that starts with `# type:` */ class TypeHintComment extends Comment { - - TypeHintComment() { - this.getText().regexpMatch("# +type:.*") - } - + TypeHintComment() { this.getText().regexpMatch("# +type:.*") } } - diff --git a/python/ql/src/semmle/python/Comparisons.qll b/python/ql/src/semmle/python/Comparisons.qll index 5bb7973e7b6..b6cd9ca800c 100644 --- a/python/ql/src/semmle/python/Comparisons.qll +++ b/python/ql/src/semmle/python/Comparisons.qll @@ -1,48 +1,64 @@ - import python /** A class representing the six comparison operators, ==, !=, <, <=, > and >=. */ class CompareOp extends int { - - CompareOp() { - this in [1..6] - } + CompareOp() { this in [1 .. 6] } /** Gets the logical inverse operator */ CompareOp invert() { - this = eq() and result = ne() or - this = ne() and result = eq() or - this = lt() and result = ge() or - this = gt() and result = le() or - this = le() and result = gt() or + this = eq() and result = ne() + or + this = ne() and result = eq() + or + this = lt() and result = ge() + or + this = gt() and result = le() + or + this = le() and result = gt() + or this = ge() and result = lt() } - /** Gets the reverse operator (swapping the operands) */ + /** Gets the reverse operator (swapping the operands) */ CompareOp reverse() { - this = eq() and result = eq() or - this = ne() and result = ne() or - this = lt() and result = gt() or - this = gt() and result = lt() or - this = le() and result = ge() or + this = eq() and result = eq() + or + this = ne() and result = ne() + or + this = lt() and result = gt() + or + this = gt() and result = lt() + or + this = le() and result = ge() + or this = ge() and result = le() } string repr() { - this = eq() and result = "==" or - this = ne() and result = "!=" or - this = lt() and result = "<" or - this = gt() and result = ">" or - this = le() and result = "<=" or + this = eq() and result = "==" + or + this = ne() and result = "!=" + or + this = lt() and result = "<" + or + this = gt() and result = ">" + or + this = le() and result = "<=" + or this = ge() and result = ">=" } predicate forOp(Cmpop op) { - op instanceof Eq and this = eq() or - op instanceof NotEq and this = ne() or - op instanceof Lt and this = lt() or - op instanceof LtE and this = le() or - op instanceof Gt and this = gt() or + op instanceof Eq and this = eq() + or + op instanceof NotEq and this = ne() + or + op instanceof Lt and this = lt() + or + op instanceof LtE and this = le() + or + op instanceof Gt and this = gt() + or op instanceof GtE and this = ge() } @@ -52,31 +68,37 @@ class CompareOp extends int { or result = this.invert() and isTrue = false } - } CompareOp eq() { result = 1 } + CompareOp ne() { result = 2 } + CompareOp lt() { result = 3 } + CompareOp le() { result = 4 } + CompareOp gt() { result = 5 } + CompareOp ge() { result = 6 } /* Workaround precision limits in floating point numbers */ -bindingset[x] private predicate ok_magnitude(float x) { - x > -9007199254740992.0 // -2**53 - and +bindingset[x] +private predicate ok_magnitude(float x) { + x > -9007199254740992.0 and // -2**53 x < 9007199254740992.0 // 2**53 } -bindingset[x,y] private float add(float x, float y) { +bindingset[x, y] +private float add(float x, float y) { ok_magnitude(x) and ok_magnitude(y) and ok_magnitude(result) and result = x + y } -bindingset[x,y] private float sub(float x, float y) { +bindingset[x, y] +private float sub(float x, float y) { ok_magnitude(x) and ok_magnitude(y) and ok_magnitude(result) and @@ -84,7 +106,9 @@ bindingset[x,y] private float sub(float x, float y) { } /** Normalise equality cmp into the form `left op right + k`. */ -private predicate test(ControlFlowNode cmp, ControlFlowNode left, CompareOp op, ControlFlowNode right, float k) { +private predicate test( + ControlFlowNode cmp, ControlFlowNode left, CompareOp op, ControlFlowNode right, float k +) { simple_test(cmp, left, op, right) and k = 0 or add_test(cmp, left, op, right, k) @@ -98,82 +122,106 @@ private predicate test(ControlFlowNode cmp, ControlFlowNode left, CompareOp op, /** Various simple tests in left op right + k form. */ private predicate simple_test(CompareNode cmp, ControlFlowNode l, CompareOp cmpop, ControlFlowNode r) { - exists(Cmpop op | - cmp.operands(l, op, r) and cmpop.forOp(op) - ) + exists(Cmpop op | cmp.operands(l, op, r) and cmpop.forOp(op)) } -private predicate add_test_left(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - exists(BinaryExprNode lhs, float c, float x, Num n | +private predicate add_test_left( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + exists(BinaryExprNode lhs, float c, float x, Num n | lhs.getNode().getOp() instanceof Add and - test(cmp, lhs, op, r, c) and x = n.getN().toFloat() and k = sub(c, x) | + test(cmp, lhs, op, r, c) and + x = n.getN().toFloat() and + k = sub(c, x) + | l = lhs.getLeft() and n = lhs.getRight().getNode() or l = lhs.getRight() and n = lhs.getLeft().getNode() ) } -private predicate add_test_right(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +private predicate add_test_right( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { exists(BinaryExprNode rhs, float c, float x, Num n | rhs.getNode().getOp() instanceof Add and - test(cmp, l, op, rhs, c) and x = n.getN().toFloat() and k = add(c, x) | + test(cmp, l, op, rhs, c) and + x = n.getN().toFloat() and + k = add(c, x) + | r = rhs.getLeft() and n = rhs.getRight().getNode() or r = rhs.getRight() and n = rhs.getLeft().getNode() ) } -/* left + x op right + c => left op right + (c-x) - left op (right + x) + c => left op right + (c+x) */ -private predicate add_test(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +/* + * left + x op right + c => left op right + (c-x) + * left op (right + x) + c => left op right + (c+x) + */ + +private predicate add_test( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { add_test_left(cmp, l, op, r, k) or - add_test_right(cmp, l, op ,r, k) + add_test_right(cmp, l, op, r, k) } -private predicate subtract_test_left(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - exists(BinaryExprNode lhs, float c, float x, Num n | +private predicate subtract_test_left( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + exists(BinaryExprNode lhs, float c, float x, Num n | lhs.getNode().getOp() instanceof Sub and test(cmp, lhs, op, r, c) and - l = lhs.getLeft() and n = lhs.getRight().getNode() and - x = n.getN().toFloat() | + l = lhs.getLeft() and + n = lhs.getRight().getNode() and + x = n.getN().toFloat() + | k = add(c, x) ) } -private predicate subtract_test_right(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +private predicate subtract_test_right( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { exists(BinaryExprNode rhs, float c, float x, Num n | rhs.getNode().getOp() instanceof Sub and test(cmp, l, op, rhs, c) and - r = rhs.getRight() and n = rhs.getLeft().getNode() and - x = n.getN().toFloat() | + r = rhs.getRight() and + n = rhs.getLeft().getNode() and + x = n.getN().toFloat() + | k = sub(c, x) ) } -/* left - x op right + c => left op right + (c+x) - left op (right - x) + c => left op right + (c-x) */ -private predicate subtract_test(CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { +/* + * left - x op right + c => left op right + (c+x) + * left op (right - x) + c => left op right + (c-x) + */ + +private predicate subtract_test( + CompareNode cmp, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { subtract_test_left(cmp, l, op, r, k) or subtract_test_right(cmp, l, op, r, k) } -private predicate not_test(UnaryExprNode u, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { - u.getNode().getOp() instanceof Not - and +private predicate not_test( + UnaryExprNode u, ControlFlowNode l, CompareOp op, ControlFlowNode r, float k +) { + u.getNode().getOp() instanceof Not and test(u.getOperand(), l, op.invert(), r, k) } - -/** A comparison which can be simplified to the canonical form `x OP y + k` where `x` and `y` are `ControlFlowNode`s, +/** + * A comparison which can be simplified to the canonical form `x OP y + k` where `x` and `y` are `ControlFlowNode`s, * `k` is a floating point constant and `OP` is one of `<=`, `>`, `==` or `!=`. */ class Comparison extends ControlFlowNode { - - Comparison() { - test(this, _, _, _, _) - } + Comparison() { test(this, _, _, _, _) } /** Whether this condition tests `l op r + k` */ predicate tests(ControlFlowNode l, CompareOp op, ControlFlowNode r, float k) { @@ -182,14 +230,14 @@ class Comparison extends ControlFlowNode { /** Whether this condition tests `l op k` */ predicate tests(ControlFlowNode l, CompareOp op, float k) { - exists(ControlFlowNode r, float x, float c | - test(this, l, op, r, c) | + exists(ControlFlowNode r, float x, float c | test(this, l, op, r, c) | x = r.getNode().(Num).getN().toFloat() and k = add(c, x) ) } - /* The following predicates determine whether this test, when its result is `thisIsTrue`, + /* + * The following predicates determine whether this test, when its result is `thisIsTrue`, * is equivalent to the predicate `v OP k` or `v1 OP v2 + k`. * For example, the test `x <= y` being false, is equivalent to the predicate `x > y`. */ @@ -242,7 +290,8 @@ class Comparison extends ControlFlowNode { this.tests(v1.getAUse(), ge().conditional(thisIsTrue), v2.getAUse(), k) } - /** Whether the result of this comparison being `thisIsTrue` implies that the result of `that` is `isThatTrue`. + /** + * Whether the result of this comparison being `thisIsTrue` implies that the result of `that` is `isThatTrue`. * In other words, does the predicate that is equivalent to the result of `this` being `thisIsTrue` * imply the predicate that is equivalent to the result of `that` being `thatIsTrue`. * For example, assume that there are two tests, which when normalised have the form `x < y` and `x > y + 1`. @@ -315,7 +364,7 @@ class Comparison extends ControlFlowNode { this.equivalentToGt(thisIsTrue, v, k1) and that.equivalentToGtEq(thatIsTrue, v, k2) and ge(k1, k2) - or + or /* `v >= k1` => `v > k2` iff k1 > k2 */ this.equivalentToGtEq(thisIsTrue, v, k1) and that.equivalentToGt(thatIsTrue, v, k2) and @@ -402,7 +451,6 @@ class Comparison extends ControlFlowNode { ge(k1, k2) ) } - } /* Work around differences in floating-point comparisons between Python and QL */ @@ -412,41 +460,27 @@ private predicate is_zero(float x) { x = -0.0 } -bindingset[x,y] private predicate lt(float x, float y) { - if is_zero(x) then - y > 0 - else - x < y -} +bindingset[x, y] +private predicate lt(float x, float y) { if is_zero(x) then y > 0 else x < y } -bindingset[x,y] private predicate eq(float x, float y) { - if is_zero(x) then - is_zero(y) - else - x = y -} +bindingset[x, y] +private predicate eq(float x, float y) { if is_zero(x) then is_zero(y) else x = y } -bindingset[x,y] private predicate gt(float x, float y) { - lt(y, x) -} +bindingset[x, y] +private predicate gt(float x, float y) { lt(y, x) } -bindingset[x,y] private predicate le(float x, float y) { - lt(x, y) or eq(x, y) -} +bindingset[x, y] +private predicate le(float x, float y) { lt(x, y) or eq(x, y) } -bindingset[x,y] private predicate ge(float x, float y) { - lt(y, x) or eq(x, y) -} +bindingset[x, y] +private predicate ge(float x, float y) { lt(y, x) or eq(x, y) } - -/** A basic block which terminates in a condition, splitting the subsequent control flow, +/** + * A basic block which terminates in a condition, splitting the subsequent control flow, * in which the condition is an instance of `Comparison` */ class ComparisonControlBlock extends ConditionBlock { - - ComparisonControlBlock() { - this.getLastNode() instanceof Comparison - } + ComparisonControlBlock() { this.getLastNode() instanceof Comparison } /** Whether this conditional guard determines that, in block `b`, `l == r + k` if `eq` is true, or `l != r + k` if `eq` is false, */ predicate controls(ControlFlowNode l, CompareOp op, ControlFlowNode r, float k, BasicBlock b) { @@ -466,16 +500,13 @@ class ComparisonControlBlock extends ConditionBlock { ) } - Comparison getTest() { - this.getLastNode() = result - } + Comparison getTest() { this.getLastNode() = result } /** Whether this conditional guard implies that, in block `b`, the result of `that` is `thatIsTrue` */ predicate impliesThat(BasicBlock b, Comparison that, boolean thatIsTrue) { exists(boolean controlSense | - this.controls(b, controlSense) and + this.controls(b, controlSense) and this.getTest().impliesThat(controlSense, that, thatIsTrue) ) } - } diff --git a/python/ql/src/semmle/python/Comprehensions.qll b/python/ql/src/semmle/python/Comprehensions.qll index eec5dd372f6..d3cd82d4fd6 100644 --- a/python/ql/src/semmle/python/Comprehensions.qll +++ b/python/ql/src/semmle/python/Comprehensions.qll @@ -1,8 +1,7 @@ import python - + /** Base class for list, set and dictionary comprehensions, and generator expressions. */ abstract class Comp extends Expr { - abstract Function getFunction(); /** Gets the iteration variable for the nth innermost generator of this list comprehension */ @@ -13,35 +12,30 @@ abstract class Comp extends Expr { private For getNthInnerLoop(int n) { n = 0 and result = this.getFunction().getStmt(0) or - result = this.getNthInnerLoop(n-1).getStmt(0) + result = this.getNthInnerLoop(n - 1).getStmt(0) } /** Gets the iteration variable for a generator of this list comprehension */ - Variable getAnIterationVariable() { - result = this.getIterationVariable(_) - } + Variable getAnIterationVariable() { result = this.getIterationVariable(_) } /** Gets the scope in which the body of this list comprehension evaluates. */ - Scope getEvaluatingScope() { - result = this.getFunction() - } + Scope getEvaluatingScope() { result = this.getFunction() } /** Gets the expression for elements of this comprehension. */ Expr getElt() { exists(Yield yield, Stmt body | result = yield.getValue() and - body = this.getNthInnerLoop(_).getAStmt() | + body = this.getNthInnerLoop(_).getAStmt() + | yield = body.(ExprStmt).getValue() or yield = body.(If).getStmt(0).(ExprStmt).getValue() ) } - } /** A list comprehension, such as `[ chr(x) for x in range(ord('A'), ord('Z')+1) ]` */ class ListComp extends ListComp_, Comp { - override Expr getASubExpression() { result = this.getAGenerator().getASubExpression() or result = this.getElt() or @@ -54,9 +48,7 @@ class ListComp extends ListComp_, Comp { result = this.getFunction() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } /** Gets the scope in which the body of this list comprehension evaluates. */ override Scope getEvaluatingScope() { @@ -66,89 +58,53 @@ class ListComp extends ListComp_, Comp { } /** Gets the iteration variable for the nth innermost generator of this list comprehension */ - override Variable getIterationVariable(int n) { - result = Comp.super.getIterationVariable(n) - } + override Variable getIterationVariable(int n) { result = Comp.super.getIterationVariable(n) } - override Function getFunction() { - result = ListComp_.super.getFunction() - } + override Function getFunction() { result = ListComp_.super.getFunction() } - override string toString() { - result = ListComp_.super.toString() - } - - override Expr getElt() { - result = Comp.super.getElt() - } + override string toString() { result = ListComp_.super.toString() } + override Expr getElt() { result = Comp.super.getElt() } } - /** A set comprehension such as `{ v for v in "0123456789" }` */ class SetComp extends SetComp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = SetComp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = SetComp_.super.getFunction() } } /** A dictionary comprehension, such as `{ k:v for k, v in enumerate("0123456789") }` */ class DictComp extends DictComp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = DictComp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = DictComp_.super.getFunction() } } - /** A generator expression, such as `(var for var in iterable)` */ class GeneratorExp extends GeneratorExp_, Comp { - - override Expr getASubExpression() { - result = this.getIterable() - } + override Expr getASubExpression() { result = this.getIterable() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getFunction() } - override predicate hasSideEffects() { - any() - } - - override Function getFunction() { - result = GeneratorExp_.super.getFunction() - } + override predicate hasSideEffects() { any() } + override Function getFunction() { result = GeneratorExp_.super.getFunction() } } - diff --git a/python/ql/src/semmle/python/Constants.qll b/python/ql/src/semmle/python/Constants.qll index c95f6bf9dc5..6ca694a3ad1 100644 --- a/python/ql/src/semmle/python/Constants.qll +++ b/python/ql/src/semmle/python/Constants.qll @@ -8,30 +8,25 @@ int major_version() { or not explicit_major_version(_) and /* If there is more than one version, prefer 2 for backwards compatibilty */ - ( - if py_flags_versioned("version.major", "2", "2") then - result = 2 - else - result = 3 - ) + (if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3) } /** the Python minor version number */ int minor_version() { exists(string v | py_flags_versioned("version.minor", v, major_version().toString()) | - result = v.toInt()) - + result = v.toInt() + ) } /** the Python micro version number */ int micro_version() { exists(string v | py_flags_versioned("version.micro", v, major_version().toString()) | - result = v.toInt()) + result = v.toInt() + ) } private predicate explicit_major_version(int v) { - exists(string version | - py_flags_versioned("language.version", version, _) | + exists(string version | py_flags_versioned("language.version", version, _) | version.charAt(0) = "2" and v = 2 or version.charAt(0) = "3" and v = 3 diff --git a/python/ql/src/semmle/python/Exprs.qll b/python/ql/src/semmle/python/Exprs.qll index 37e8611e925..2b58fe38e4e 100644 --- a/python/ql/src/semmle/python/Exprs.qll +++ b/python/ql/src/semmle/python/Exprs.qll @@ -4,26 +4,19 @@ private import semmle.python.objects.ObjectInternal /** An expression */ class Expr extends Expr_, AstNode { - /** Gets the scope of this expression */ - override Scope getScope() { - py_scopes(this, result) - } + override Scope getScope() { py_scopes(this, result) } - override string toString() { - result = "Expression" - } + override string toString() { result = "Expression" } /** Gets the module in which this expression occurs */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } - /** Whether this expression defines variable `v` - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ - predicate defines(Variable v) { - this.getASubExpression+().defines(v) - } + /** + * Whether this expression defines variable `v` + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ + predicate defines(Variable v) { this.getASubExpression+().defines(v) } /** Whether this expression may have a side effect (as determined purely from its syntax) */ predicate hasSideEffects() { @@ -34,66 +27,57 @@ class Expr extends Expr_, AstNode { } /** Whether this expression is a constant */ - predicate isConstant() { - not this.isVariable() - } + predicate isConstant() { not this.isVariable() } /** Use isParenthesized instead. */ - override deprecated predicate isParenthesised() { - this.isParenthesized() - } + deprecated override predicate isParenthesised() { this.isParenthesized() } /** Whether the parenthesized property of this expression is true. */ - predicate isParenthesized() { - Expr_.super.isParenthesised() - } + predicate isParenthesized() { Expr_.super.isParenthesised() } private predicate isVariable() { - this.hasSideEffects() or - this instanceof Name or + this.hasSideEffects() + or + this instanceof Name + or exists(Expr e | e = this.getASubExpression() and e.isVariable()) } - override Location getLocation() { - result = Expr_.super.getLocation() - } + override Location getLocation() { result = Expr_.super.getLocation() } /** Gets an immediate (non-nested) sub-expression of this expression */ - Expr getASubExpression() { - none() - } + Expr getASubExpression() { none() } /** Use StrConst.getText() instead */ - deprecated string strValue() { - none() - } + deprecated string strValue() { none() } - override AstNode getAChildNode() { - result = this.getASubExpression() - } + override AstNode getAChildNode() { result = this.getASubExpression() } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. * Gets what this expression might "refer-to". Performs a combination of localized (intra-procedural) points-to * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly - * precise, but may not provide information for a significant number of flow-nodes. + * precise, but may not provide information for a significant number of flow-nodes. * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. - * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use + * NOTE: For complex dataflow, involving multiple stages of points-to analysis, it may be more precise to use * `ControlFlowNode.refersTo(...)` instead. */ predicate refersTo(Object obj, ClassObject cls, AstNode origin) { this.refersTo(_, obj, cls, origin) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. * Gets what this expression might "refer-to" in the given `context`. */ predicate refersTo(Context context, Object obj, ClassObject cls, AstNode origin) { this.getAFlowNode().refersTo(context, obj, cls, origin.getAFlowNode()) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Holds if this expression might "refer-to" to `value` which is from `origin` - * Unlike `this.refersTo(value, _, origin)`, this predicate includes results + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Holds if this expression might "refer-to" to `value` which is from `origin` + * Unlike `this.refersTo(value, _, origin)`, this predicate includes results * where the class cannot be inferred. */ pragma[nomagic] @@ -101,36 +85,34 @@ class Expr extends Expr_, AstNode { this.getAFlowNode().refersTo(obj, origin.getAFlowNode()) } - /** NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. - * Equivalent to `this.refersTo(value, _)` */ - predicate refersTo(Object obj) { - this.refersTo(obj, _) - } + /** + * NOTE: `refersTo` will be deprecated in 2019. Use `pointsTo` instead. + * Equivalent to `this.refersTo(value, _)` + */ + predicate refersTo(Object obj) { this.refersTo(obj, _) } - /** Holds if this expression might "point-to" to `value` which is from `origin` + /** + * Holds if this expression might "point-to" to `value` which is from `origin` * in the given `context`. */ predicate pointsTo(Context context, Value value, AstNode origin) { this.getAFlowNode().pointsTo(context, value, origin.getAFlowNode()) } - /** Holds if this expression might "point-to" to `value` which is from `origin`. + /** + * Holds if this expression might "point-to" to `value` which is from `origin`. */ predicate pointsTo(Value value, AstNode origin) { this.getAFlowNode().pointsTo(value, origin.getAFlowNode()) } - /** Holds if this expression might "point-to" to `value`. + /** + * Holds if this expression might "point-to" to `value`. */ - predicate pointsTo(Value value) { - this.pointsTo(value, _) - } + predicate pointsTo(Value value) { this.pointsTo(value, _) } /** Gets a value that this expression might "point-to". */ - Value pointsTo() { - this.pointsTo(result) - } - + Value pointsTo() { this.pointsTo(result) } } /** An assignment expression, such as `x := y` */ @@ -143,103 +125,82 @@ class AssignExpr extends AssignExpr_ { /** An attribute expression, such as `value.attr` */ class Attribute extends Attribute_ { - /* syntax: Expr.name */ - - override Expr getASubExpression() { - result = this.getObject() - } + override Expr getASubExpression() { result = this.getObject() } override AttrNode getAFlowNode() { result = super.getAFlowNode() } - /** Gets the name of this attribute. That is the `name` in `obj.name` */ - string getName() { - result = Attribute_.super.getAttr() - } + string getName() { result = Attribute_.super.getAttr() } /** Gets the object of this attribute. That is the `obj` in `obj.name` */ - Expr getObject() { - result = Attribute_.super.getValue() - } + Expr getObject() { result = Attribute_.super.getValue() } - /** Gets the expression corresponding to the object of the attribute, if the name of the attribute is `name`. - * Equivalent to `this.getObject() and this.getName() = name`. */ + /** + * Gets the expression corresponding to the object of the attribute, if the name of the attribute is `name`. + * Equivalent to `this.getObject() and this.getName() = name`. + */ Expr getObject(string name) { result = Attribute_.super.getValue() and name = Attribute_.super.getAttr() } - } /** A subscript expression, such as `value[slice]` */ class Subscript extends Subscript_ { - /* syntax: Expr[Expr] */ - override Expr getASubExpression() { result = this.getIndex() or result = this.getObject() } - Expr getObject() { - result = Subscript_.super.getValue() - } + Expr getObject() { result = Subscript_.super.getValue() } override SubscriptNode getAFlowNode() { result = super.getAFlowNode() } } /** A call expression, such as `func(...)` */ class Call extends Call_ { - /* syntax: Expr(...) */ - override Expr getASubExpression() { result = this.getAPositionalArg() or result = this.getAKeyword().getValue() or result = this.getFunc() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } - override string toString() { - result = this.getFunc().toString() + "()" - } + override string toString() { result = this.getFunc().toString() + "()" } override CallNode getAFlowNode() { result = super.getAFlowNode() } /** Gets a tuple (*) argument of this call. */ - Expr getStarargs() { - result = this.getAPositionalArg().(Starred).getValue() - } + Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() } /** Gets a dictionary (**) argument of this call. */ - Expr getKwargs() { - result = this.getANamedArg().(DictUnpacking).getValue() - } + Expr getKwargs() { result = this.getANamedArg().(DictUnpacking).getValue() } /* Backwards compatibility */ - - /** Gets the nth keyword argument of this call expression, provided it is not preceded by a double-starred argument. + /** + * Gets the nth keyword argument of this call expression, provided it is not preceded by a double-starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getNamedArg(index) instead. - * */ + */ Keyword getKeyword(int index) { - result = this.getNamedArg(index) and not exists(DictUnpacking d, int lower | d = this.getNamedArg(lower) and lower < index) + result = this.getNamedArg(index) and + not exists(DictUnpacking d, int lower | d = this.getNamedArg(lower) and lower < index) } - /** Gets a keyword argument of this call expression, provided it is not preceded by a double-starred argument. + /** + * Gets a keyword argument of this call expression, provided it is not preceded by a double-starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getANamedArg() instead. - * */ - Keyword getAKeyword() { - result = this.getKeyword(_) - } + */ + Keyword getAKeyword() { result = this.getKeyword(_) } - /** Gets the positional argument at `index`, provided it is not preceded by a starred argument. + /** + * Gets the positional argument at `index`, provided it is not preceded by a starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getPositionalArg(index) instead. */ @@ -249,13 +210,12 @@ class Call extends Call_ { not exists(Starred s, int lower | s = this.getPositionalArg(lower) and lower < index) } - /** Gets a positional argument, provided it is not preceded by a starred argument. + /** + * Gets a positional argument, provided it is not preceded by a starred argument. * This exists primarily for backwards compatibility. You are recommended to use * Call.getAPositionalArg() instead. */ - Expr getAnArg() { - result = this.getArg(_) - } + Expr getAnArg() { result = this.getArg(_) } override AstNode getAChildNode() { result = this.getAPositionalArg() or @@ -281,14 +241,11 @@ class Call extends Call_ { count(this.getStarargs()) < 2 and result = getStarargs() } - } /** A conditional expression such as, `body if test else orelse` */ class IfExp extends IfExp_ { - /* syntax: Expr if Expr else Expr */ - override Expr getASubExpression() { result = this.getTest() or result = this.getBody() or result = this.getOrelse() } @@ -298,151 +255,96 @@ class IfExp extends IfExp_ { /** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */ class Starred extends Starred_ { - /* syntax: *Expr */ - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } - /** A yield expression, such as `yield value` */ class Yield extends Yield_ { - /* syntax: yield Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /** A yield expression, such as `yield from value` */ class YieldFrom extends YieldFrom_ { - /* syntax: yield from Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /** A repr (backticks) expression, such as `` `value` `` */ class Repr extends Repr_ { - /* syntax: `Expr` */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override predicate hasSideEffects() { - any() - } - + override predicate hasSideEffects() { any() } } /* Constants */ - -/** A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as - * `"hello"` are treated as Bytes for Python2, but Unicode for Python3. */ +/** + * A bytes constant, such as `b'ascii'`. Note that unadorned string constants such as + * `"hello"` are treated as Bytes for Python2, but Unicode for Python3. + */ class Bytes extends StrConst { - /* syntax: b"hello" */ - - Bytes() { - not this.isUnicode() - } + Bytes() { not this.isUnicode() } override Object getLiteralObject() { py_cobjecttypes(result, theBytesType()) and py_cobjectnames(result, this.quotedString()) } - /** The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). + /** + * The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). * The following predicate help us match up a string/byte literals in the source * which the equivalent object. */ private string quotedString() { - exists(string b_unquoted | - b_unquoted = this.getS() | - result = "b'" + b_unquoted + "'" - ) + exists(string b_unquoted | b_unquoted = this.getS() | result = "b'" + b_unquoted + "'") } - } /** An ellipsis expression, such as `...` */ class Ellipsis extends Ellipsis_ { - /* syntax: ... */ - - override Expr getASubExpression() { - none() - } - + override Expr getASubExpression() { none() } } -/** Immutable literal expressions (except tuples). +/** + * Immutable literal expressions (except tuples). * Consists of string (both unicode and byte) literals and numeric literals. */ abstract class ImmutableLiteral extends Expr { - abstract Object getLiteralObject(); abstract boolean booleanValue(); - final Value getLiteralValue() { - result.(ConstantObjectInternal).getLiteral() = this - } - + final Value getLiteralValue() { result.(ConstantObjectInternal).getLiteral() = this } } /** A numerical constant expression, such as `7` or `4.2` */ abstract class Num extends Num_, ImmutableLiteral { - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } /* We want to declare this abstract, but currently we cannot. */ - override string toString() { - result = "Num with missing toString" - } - + override string toString() { result = "Num with missing toString" } } /** An integer numeric constant, such as `7` or `0x9` */ class IntegerLiteral extends Num { - /* syntax: 4 */ - - IntegerLiteral() { - not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral - } + IntegerLiteral() { not this instanceof FloatLiteral and not this instanceof ImaginaryLiteral } /** * Gets the (integer) value of this constant. Will not return a result if the value does not fit into - * a 32 bit signed value + * a 32 bit signed value */ - int getValue() { - result = this.getN().toInt() - } + int getValue() { result = this.getN().toInt() } - override string toString() { - result = "IntegerLiteral" - } + override string toString() { result = "IntegerLiteral" } override Object getLiteralObject() { py_cobjecttypes(result, theIntType()) and py_cobjectnames(result, this.getN()) @@ -455,29 +357,22 @@ class IntegerLiteral extends Num { or this.getValue() != 0 and result = true } - } /** A floating point numeric constant, such as `0.4` or `4e3` */ class FloatLiteral extends Num { - /* syntax: 4.2 */ - FloatLiteral() { not this instanceof ImaginaryLiteral and this.getN().regexpMatch(".*[.eE].*") } - float getValue() { - result = this.getN().toFloat() - } + float getValue() { result = this.getN().toFloat() } - override string toString() { - result = "FloatLiteral" - } + override string toString() { result = "FloatLiteral" } override Object getLiteralObject() { - py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN()) + py_cobjecttypes(result, theFloatType()) and py_cobjectnames(result, this.getN()) } override boolean booleanValue() { @@ -495,22 +390,15 @@ class ImaginaryLiteral extends Num { private float value; /* syntax: 1.0j */ - - ImaginaryLiteral() { - value = this.getN().regexpCapture("(.+)j.*", 1).toFloat() - } + ImaginaryLiteral() { value = this.getN().regexpCapture("(.+)j.*", 1).toFloat() } /** Gets the value of this constant as a floating point value */ - float getValue() { - result = value - } + float getValue() { result = value } - override string toString() { - result = "ImaginaryLiteral" - } + override string toString() { result = "ImaginaryLiteral" } override Object getLiteralObject() { - py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN()) + py_cobjecttypes(result, theComplexType()) and py_cobjectnames(result, this.getN()) } override boolean booleanValue() { @@ -521,210 +409,154 @@ class ImaginaryLiteral extends Num { or this.getValue() != 0.0 and this.getValue() != -0.0 and result = true } - } class NegativeIntegerLiteral extends ImmutableLiteral, UnaryExpr { - NegativeIntegerLiteral() { this.getOp() instanceof USub and this.getOperand() instanceof IntegerLiteral } - override boolean booleanValue() { - result = this.getOperand().(IntegerLiteral).booleanValue() - } + override boolean booleanValue() { result = this.getOperand().(IntegerLiteral).booleanValue() } override Object getLiteralObject() { - (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) - and + (py_cobjecttypes(result, theIntType()) or py_cobjecttypes(result, theLongType())) and py_cobjectnames(result, "-" + this.getOperand().(IntegerLiteral).getN()) } - /** + /** * Gets the (integer) value of this constant. Will not return a result if the value does not fit into - * a 32 bit signed value + * a 32 bit signed value */ - int getValue() { - result = -(this.getOperand().(IntegerLiteral).getValue()) - } - + int getValue() { result = -this.getOperand().(IntegerLiteral).getValue() } } -/** A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as - * "hello" are treated as Bytes for Python2, but Unicode for Python3. +/** + * A unicode string expression, such as `u"\u20ac"`. Note that unadorned string constants such as + * "hello" are treated as Bytes for Python2, but Unicode for Python3. */ class Unicode extends StrConst { - /* syntax: "hello" */ - - Unicode() { - this.isUnicode() - } + Unicode() { this.isUnicode() } override Object getLiteralObject() { py_cobjecttypes(result, theUnicodeType()) and py_cobjectnames(result, this.quotedString()) } - /** The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). + /** + * The extractor puts quotes into the name of each string (to prevent "0" clashing with 0). * The following predicate help us match up a string/byte literals in the source * which the equivalent object. */ string quotedString() { - exists(string u_unquoted | - u_unquoted = this.getS() | - result = "u'" + u_unquoted + "'" - ) + exists(string u_unquoted | u_unquoted = this.getS() | result = "u'" + u_unquoted + "'") } - } - /* Compound Values */ - /** A dictionary expression, such as `{'key':'value'}` */ class Dict extends Dict_ { - /* syntax: {Expr: Expr, ...} */ - /** Gets the value of an item of this dict display */ - Expr getAValue() { - result = this.getAnItem().(DictDisplayItem).getValue() - } + Expr getAValue() { result = this.getAnItem().(DictDisplayItem).getValue() } - /** Gets the key of an item of this dict display, for those items that have keys + /** + * Gets the key of an item of this dict display, for those items that have keys * E.g, in {'a':1, **b} this returns only 'a' */ - Expr getAKey() { - result = this.getAnItem().(KeyValuePair).getKey() - } + Expr getAKey() { result = this.getAnItem().(KeyValuePair).getKey() } - override Expr getASubExpression() { - result = this.getAValue() or result = this.getAKey() - } - - override AstNode getAChildNode() { - result = this.getAnItem() - } + override Expr getASubExpression() { result = this.getAValue() or result = this.getAKey() } + override AstNode getAChildNode() { result = this.getAnItem() } } /** A list expression, such as `[ 1, 3, 5, 7, 9 ]` */ class List extends List_ { - /* syntax: [Expr, ...] */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } /** A set expression such as `{ 1, 3, 5, 7, 9 }` */ class Set extends Set_ { - /* syntax: {Expr, ...} */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } class PlaceHolder extends PlaceHolder_ { + string getId() { result = this.getVariable().getId() } - string getId() { - result = this.getVariable().getId() - } + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override string toString() { - result = "$" + this.getId() - } + override string toString() { result = "$" + this.getId() } override NameNode getAFlowNode() { result = super.getAFlowNode() } } /** A tuple expression such as `( 1, 3, 5, 7, 9 )` */ class Tuple extends Tuple_ { - /* syntax: (Expr, ...) */ - - override Expr getASubExpression() { - result = this.getAnElt() - } - + override Expr getASubExpression() { result = this.getAnElt() } } -/** A (plain variable) name expression, such as `var`. +/** + * A (plain variable) name expression, such as `var`. * `None`, `True` and `False` are excluded. */ class Name extends Name_ { - /* syntax: name */ - - string getId() { - result = this.getVariable().getId() - } + string getId() { result = this.getVariable().getId() } /** Whether this expression is a definition */ predicate isDefinition() { - py_expr_contexts(_, 5, this) or + py_expr_contexts(_, 5, this) + or /* Treat Param as a definition (which it is) */ - py_expr_contexts(_, 4, this) or + py_expr_contexts(_, 4, this) + or /* The target in an augmented assignment is also a definition (and a use) */ exists(AugAssign aa | aa.getTarget() = this) } - /** Whether this expression defines variable `v` - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ + /** + * Whether this expression defines variable `v` + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ override predicate defines(Variable v) { - this.isDefinition() - and + this.isDefinition() and v = this.getVariable() } /** Whether this expression is a deletion */ - predicate isDeletion() { - py_expr_contexts(_, 2, this) - } + predicate isDeletion() { py_expr_contexts(_, 2, this) } - /** Whether this expression deletes variable `v`. - * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. */ + /** + * Whether this expression deletes variable `v`. + * If doing dataflow, then consider using SsaVariable.getDefinition() for more precision. + */ predicate deletes(Variable v) { - this.isDeletion() - and + this.isDeletion() and v = this.getVariable() } /** Whether this expression is a use */ - predicate isUse() { - py_expr_contexts(_, 3, this) - } + predicate isUse() { py_expr_contexts(_, 3, this) } - /** Whether this expression is a use of variable `v` - * If doing dataflow, then consider using SsaVariable.getAUse() for more precision. */ + /** + * Whether this expression is a use of variable `v` + * If doing dataflow, then consider using SsaVariable.getAUse() for more precision. + */ predicate uses(Variable v) { - this.isUse() - and + this.isUse() and v = this.getVariable() } - override predicate isConstant() { - none() - } + override predicate isConstant() { none() } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override string toString() { - result = this.getId() - } + override string toString() { result = this.getId() } override NameNode getAFlowNode() { result = super.getAFlowNode() } @@ -732,36 +564,28 @@ class Name extends Name_ { /* Artificial variable names in comprehensions all start with "." */ this.getId().charAt(0) = "." } - } class Filter extends Filter_ { - override Expr getASubExpression() { result = this.getFilter() or result = this.getValue() } - } - /** A slice. E.g `0:1` in the expression `x[0:1]` */ class Slice extends Slice_ { - override Expr getASubExpression() { result = this.getStart() or result = this.getStop() or result = this.getStep() } - } /** A string constant. */ class StrConst extends Str_, ImmutableLiteral { - /* syntax: "hello" */ - predicate isUnicode() { this.getPrefix().charAt(_) = "u" or @@ -769,31 +593,21 @@ class StrConst extends Str_, ImmutableLiteral { or not this.getPrefix().charAt(_) = "b" and major_version() = 3 or - not this.getPrefix().charAt(_) = "b" and this.getEnclosingModule().hasFromFuture("unicode_literals") + not this.getPrefix().charAt(_) = "b" and + this.getEnclosingModule().hasFromFuture("unicode_literals") } - override - string strValue() { - result = this.getS() - } + override string strValue() { result = this.getS() } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override AstNode getAChildNode() { - result = this.getAnImplicitlyConcatenatedPart() - } + override AstNode getAChildNode() { result = this.getAnImplicitlyConcatenatedPart() } /** Gets the text of this str constant */ - string getText() { - result = this.getS() - } + string getText() { result = this.getS() } /** Whether this is a docstring */ - predicate isDocString() { - exists(Scope s | s.getDocString() = this) - } + predicate isDocString() { exists(Scope s | s.getDocString() = this) } override boolean booleanValue() { this.getText() = "" and result = false @@ -802,174 +616,103 @@ class StrConst extends Str_, ImmutableLiteral { } override Object getLiteralObject() { none() } - } private predicate name_consts(Name_ n, string id) { - exists(Variable v | - py_variables(v, n) and id = v.getId() | + exists(Variable v | py_variables(v, n) and id = v.getId() | id = "True" or id = "False" or id = "None" ) } /** A named constant, one of `None`, `True` or `False` */ abstract class NameConstant extends Name, ImmutableLiteral { + NameConstant() { name_consts(this, _) } - NameConstant() { - name_consts(this, _) - } + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } + override string toString() { name_consts(this, result) } - override string toString() { - name_consts(this, result) - } - - override predicate isConstant() { - any() - } + override predicate isConstant() { any() } override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() } - override predicate isArtificial() { - none() - } - + override predicate isArtificial() { none() } } /** A boolean named constant, either `True` or `False` */ -abstract class BooleanLiteral extends NameConstant { - -} +abstract class BooleanLiteral extends NameConstant { } /** The boolean named constant `True` */ class True extends BooleanLiteral { - /* syntax: True */ + True() { name_consts(this, "True") } - True() { - name_consts(this, "True") - } - - override Object getLiteralObject() { - name_consts(this, "True") and result = theTrueObject() - } - - override boolean booleanValue() { - result = true - } + override Object getLiteralObject() { name_consts(this, "True") and result = theTrueObject() } + override boolean booleanValue() { result = true } } /** The boolean named constant `False` */ class False extends BooleanLiteral { - /* syntax: False */ + False() { name_consts(this, "False") } - False() { - name_consts(this, "False") - } - - override Object getLiteralObject() { - name_consts(this, "False") and result = theFalseObject() - } - - override boolean booleanValue() { - result = false - } + override Object getLiteralObject() { name_consts(this, "False") and result = theFalseObject() } + override boolean booleanValue() { result = false } } /** `None` */ class None extends NameConstant { - /* syntax: None */ + None() { name_consts(this, "None") } - None() { - name_consts(this, "None") - } + override Object getLiteralObject() { name_consts(this, "None") and result = theNoneObject() } - override Object getLiteralObject() { - name_consts(this, "None") and result = theNoneObject() - } - - override boolean booleanValue() { - result = false - } + override boolean booleanValue() { result = false } } /** An await expression such as `await coro`. */ class Await extends Await_ { - /* syntax: await Expr */ - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } /** A formatted string literal expression, such as `f'hello {world!s}'` */ class Fstring extends Fstring_ { - /* syntax: f"Yes!" */ - - override Expr getASubExpression() { - result = this.getAValue() - } - + override Expr getASubExpression() { result = this.getAValue() } } -/** A formatted value (within a formatted string literal). +/** + * A formatted value (within a formatted string literal). * For example, in the string `f'hello {world!s}'` the formatted value is `world!s`. */ class FormattedValue extends FormattedValue_ { - override Expr getASubExpression() { result = this.getValue() or result = this.getFormatSpec() } - - } /* Expression Contexts */ - /** A context in which an expression used */ -class ExprContext extends ExprContext_ { - -} +class ExprContext extends ExprContext_ { } /** Load context, the context of var in len(var) */ -class Load extends Load_ { - -} +class Load extends Load_ { } /** Store context, the context of var in var = 0 */ -class Store extends Store_ { - -} +class Store extends Store_ { } /** Delete context, the context of var in del var */ -class Del extends Del_ { - -} +class Del extends Del_ { } /** This is an artifact of the Python grammar which includes an AugLoad context, even though it is never used. */ -library class AugLoad extends AugLoad_ { - -} +library class AugLoad extends AugLoad_ { } /** Augmented store context, the context of var in var += 1 */ -class AugStore extends AugStore_ { - -} +class AugStore extends AugStore_ { } /** Parameter context, the context of var in def f(var): pass */ -class Param extends Param_ { - -} - - +class Param extends Param_ { } diff --git a/python/ql/src/semmle/python/Files.qll b/python/ql/src/semmle/python/Files.qll index 461279c50e2..77f146d13cb 100644 --- a/python/ql/src/semmle/python/Files.qll +++ b/python/ql/src/semmle/python/Files.qll @@ -1,22 +1,14 @@ - import python /** A file */ class File extends Container { - - File() { - files(this, _, _, _, _) - } + File() { files(this, _, _, _, _) } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated override string getName() { - result = this.getAbsolutePath() - } + deprecated override string getName() { result = this.getAbsolutePath() } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated string getFullName() { - result = this.getAbsolutePath() - } + deprecated string getFullName() { result = this.getAbsolutePath() } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0 @@ -30,8 +22,7 @@ class File extends Container { /** Gets a short name for this file (just the file name) */ string getShortName() { - exists(string simple, string ext | files(this, _, simple, ext, _) | - result = simple + ext) + exists(string simple, string ext | files(this, _, simple, ext, _) | result = simple + ext) } private int lastLine() { @@ -40,27 +31,21 @@ class File extends Container { /** Whether line n is empty (it contains neither code nor comment). */ predicate emptyLine(int n) { - n in [0..this.lastLine()] - and + n in [0 .. this.lastLine()] and not occupied_line(this, n) } string getSpecifiedEncoding() { - exists(Comment c, Location l | - l = c.getLocation() and l.getFile() = this | + exists(Comment c, Location l | l = c.getLocation() and l.getFile() = this | l.getStartLine() < 3 and result = c.getText().regexpCapture(".*coding[:=]\\s*([-\\w.]+).*", 1) ) } - override string getAbsolutePath() { - files(this, result, _, _, _) - } + override string getAbsolutePath() { files(this, result, _, _, _) } /** Gets the URL of this file. */ - override string getURL() { - result = "file://" + this.getAbsolutePath() + ":0:0:0:0" - } + override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } override Container getImportRoot(int n) { /* File stem must be a legal Python identifier */ @@ -68,56 +53,40 @@ class File extends Container { result = this.getParent().getImportRoot(n) } - /** Gets the contents of this file as a string. + /** + * Gets the contents of this file as a string. * This will only work for those non-python files that * are specified to be extracted. */ - string getContents() { - file_contents(this, result) - } - + string getContents() { file_contents(this, result) } } private predicate occupied_line(File f, int n) { - exists(Location l | - l.getFile() = f | + exists(Location l | l.getFile() = f | l.getStartLine() = n or - exists(StrConst s | s.getLocation() = l | - n in [l.getStartLine() .. l.getEndLine()] - ) - ) + exists(StrConst s | s.getLocation() = l | n in [l.getStartLine() .. l.getEndLine()]) + ) } /** A folder (directory) */ class Folder extends Container { - - Folder() { - folders(this, _, _) - } + Folder() { folders(this, _, _) } /** DEPRECATED: Use `getAbsolutePath` instead. */ - deprecated override string getName() { - result = this.getAbsolutePath() - } + deprecated override string getName() { result = this.getAbsolutePath() } /** DEPRECATED: Use `getBaseName` instead. */ - deprecated string getSimple() { - folders(this, _, result) - } + deprecated string getSimple() { folders(this, _, result) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.getAbsolutePath() = filepath and bl = 0 and bc = 0 and el = 0 and ec = 0 } - override string getAbsolutePath() { - folders(this, result, _) - } + override string getAbsolutePath() { folders(this, result, _) } /** Gets the URL of this folder. */ - override string getURL() { - result = "folder://" + this.getAbsolutePath() - } + override string getURL() { result = "folder://" + this.getAbsolutePath() } override Container getImportRoot(int n) { this.isImportRoot(n) and result = this @@ -126,32 +95,24 @@ class Folder extends Container { this.getBaseName().regexpMatch("[^\\d\\W]\\w*") and result = this.getParent().getImportRoot(n) } - } -/** +/** * A container is an abstract representation of a file system object that can - * hold elements of interest. + * hold elements of interest. */ abstract class Container extends @container { - - Container getParent() { - containerparent(result, this) - } + Container getParent() { containerparent(result, this) } /** Gets a child of this container */ - deprecated Container getChild() { - containerparent(this, result) - } + deprecated Container getChild() { containerparent(this, result) } /** * Gets a textual representation of the path of this container. * * This is the absolute path of the container. */ - string toString() { - result = this.getAbsolutePath() - } + string toString() { result = this.getAbsolutePath() } /** Gets the name of this container */ abstract string getName(); @@ -165,8 +126,9 @@ abstract class Container extends @container { * if the root folder is not a reflexive, transitive parent of this container. */ string getRelativePath() { - exists (string absPath, string pref | - absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | + exists(string absPath, string pref | + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) + | absPath = pref and result = "" or absPath = pref.regexpReplaceAll("/$", "") + "/" + result and @@ -175,36 +137,28 @@ abstract class Container extends @container { } /** Whether this file or folder is part of the standard library */ - predicate inStdlib() { - this.inStdlib(_, _) - } + predicate inStdlib() { this.inStdlib(_, _) } - /** Whether this file or folder is part of the standard library + /** + * Whether this file or folder is part of the standard library * for version `major.minor` */ predicate inStdlib(int major, int minor) { exists(Module m | - m.getPath() = this and + m.getPath() = this and m.inStdLib(major, minor) ) } /* Standard cross-language API */ - /** Gets a file or sub-folder in this container. */ - Container getAChildContainer() { - containerparent(this, result) - } + Container getAChildContainer() { containerparent(this, result) } /** Gets a file in this container. */ - File getAFile() { - result = this.getAChildContainer() - } + File getAFile() { result = this.getAChildContainer() } /** Gets a sub-folder in this container. */ - Folder getAFolder() { - result = this.getAChildContainer() - } + Folder getAFolder() { result = this.getAChildContainer() } /** * Gets the absolute, canonical path of this container, using forward slashes @@ -276,9 +230,7 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""gz" * */ - string getExtension() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) - } + string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } /** * Gets the stem of this container, that is, the prefix of its base name up to @@ -297,9 +249,7 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""x.tar" * */ - string getStem() { - result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) - } + string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } File getFile(string baseName) { result = this.getAFile() and @@ -311,9 +261,7 @@ abstract class Container extends @container { result.getBaseName() = baseName } - Container getParentContainer() { - this = result.getAChildContainer() - } + Container getParentContainer() { this = result.getAChildContainer() } Container getChildContainer(string baseName) { result = this.getAChildContainer() and @@ -328,32 +276,31 @@ abstract class Container extends @container { abstract string getURL(); /** Holds if this folder is on the import path. */ - predicate isImportRoot() { - this.isImportRoot(_) - } + predicate isImportRoot() { this.isImportRoot(_) } - /** Holds if this folder is on the import path, at index `n` in the list of + /** + * Holds if this folder is on the import path, at index `n` in the list of * paths. The list of paths is composed of the paths passed to the extractor and - * `sys.path`. */ - predicate isImportRoot(int n) { - this.getName() = import_path_element(n) - } + * `sys.path`. + */ + predicate isImportRoot(int n) { this.getName() = import_path_element(n) } /** Holds if this folder is the root folder for the standard library. */ predicate isStdLibRoot(int major, int minor) { - major = major_version() and minor = minor_version() and + major = major_version() and + minor = minor_version() and this.isStdLibRoot() } /** Holds if this folder is the root folder for the standard library. */ predicate isStdLibRoot() { - /* Look for a standard lib module and find its import path + /* + * Look for a standard lib module and find its import path * We use `os` as it is the most likely to be imported and * `tty` because it is small for testing. */ - exists(Module m | - m.getName() = "os" or m.getName() = "tty" - | + + exists(Module m | m.getName() = "os" or m.getName() = "tty" | m.getFile().getImportRoot() = this ) } @@ -371,7 +318,6 @@ abstract class Container extends @container { /** Gets the path element from which this container would be loaded, given the index into the list of possible paths `n`. */ abstract Container getImportRoot(int n); - } private string import_path_element(int n) { @@ -379,53 +325,46 @@ private string import_path_element(int n) { path = get_path("extractor.path") and k = 0 or path = get_path("sys.path") and k = count(get_path("extractor.path").splitAt(pathsep)) - | + | py_flags_versioned("os.pathsep", pathsep, _) and - result = path.splitAt(pathsep, n-k).replaceAll("\\", "/") + result = path.splitAt(pathsep, n - k).replaceAll("\\", "/") ) } -private string get_path(string name) { - py_flags_versioned(name, result, _) -} +private string get_path(string name) { py_flags_versioned(name, result, _) } class Location extends @location { - /** Gets the file for this location */ - File getFile() { - result = this.getPath() - } + File getFile() { result = this.getPath() } private Container getPath() { locations_default(this, result, _, _, _, _) or - exists(Module m | locations_ast(this, m, _, _, _, _) | - result = m.getPath() - ) + exists(Module m | locations_ast(this, m, _, _, _, _) | result = m.getPath()) } /** Gets the start line of this location */ int getStartLine() { - locations_default(this, _, result, _, _, _) - or locations_ast(this,_,result,_,_,_) + locations_default(this, _, result, _, _, _) or + locations_ast(this, _, result, _, _, _) } /** Gets the start column of this location */ int getStartColumn() { - locations_default(this, _, _, result, _, _) - or locations_ast(this, _, _, result, _, _) + locations_default(this, _, _, result, _, _) or + locations_ast(this, _, _, result, _, _) } /** Gets the end line of this location */ int getEndLine() { - locations_default(this, _, _, _, result, _) - or locations_ast(this, _, _, _, result, _) + locations_default(this, _, _, _, result, _) or + locations_ast(this, _, _, _, result, _) } /** Gets the end column of this location */ int getEndColumn() { - locations_default(this, _, _, _, _, result) - or locations_ast(this, _, _, _, _, result) + locations_default(this, _, _, _, _, result) or + locations_ast(this, _, _, _, _, result) } string toString() { @@ -436,20 +375,20 @@ class Location extends @location { exists(File f | f.getAbsolutePath() = filepath | locations_default(this, f, bl, bc, el, ec) or - exists(Module m | m.getFile() = f | - locations_ast(this, m, bl, bc, el, ec)) - ) + exists(Module m | m.getFile() = f | locations_ast(this, m, bl, bc, el, ec)) + ) } - } /** A non-empty line in the source code */ class Line extends @py_line { - predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { - exists(Module m | m.getFile().getAbsolutePath() = filepath and - el = bl and bc = 1 and - py_line_lengths(this, m, bl, ec)) + exists(Module m | + m.getFile().getAbsolutePath() = filepath and + el = bl and + bc = 1 and + py_line_lengths(this, m, bl, ec) + ) } string toString() { @@ -459,58 +398,37 @@ class Line extends @py_line { } /** Gets the line number of this line */ - int getLineNumber() { - py_line_lengths(this, _, result, _) - } + int getLineNumber() { py_line_lengths(this, _, result, _) } /** Gets the length of this line */ - int getLength() { - py_line_lengths(this, _, _, result) - } + int getLength() { py_line_lengths(this, _, _, result) } /** Gets the file for this line */ - Module getModule() { - py_line_lengths(this, result, _, _) - } - + Module getModule() { py_line_lengths(this, result, _, _) } } -/** +/** * A syntax error. Note that if there is a syntax error in a module, - * much information about that module will be lost + * much information about that module will be lost */ class SyntaxError extends Location { + SyntaxError() { py_syntax_error_versioned(this, _, major_version().toString()) } - SyntaxError() { - py_syntax_error_versioned(this, _, major_version().toString()) - } - - override string toString() { - result = "Syntax Error" - } + override string toString() { result = "Syntax Error" } /** Gets the message corresponding to this syntax error */ - string getMessage() { - py_syntax_error_versioned(this, result, major_version().toString()) - } - + string getMessage() { py_syntax_error_versioned(this, result, major_version().toString()) } } -/** +/** * An encoding error. Note that if there is an encoding error in a module, - * much information about that module will be lost + * much information about that module will be lost */ class EncodingError extends SyntaxError { - EncodingError() { /* Leave spaces around 'decode' in unlikely event it occurs as a name in a syntax error */ this.getMessage().toLowerCase().matches("% decode %") } - override string toString() { - result = "Encoding Error" - } - + override string toString() { result = "Encoding Error" } } - - diff --git a/python/ql/src/semmle/python/Flow.qll b/python/ql/src/semmle/python/Flow.qll index 15d10694714..e92db18c3cf 100755 --- a/python/ql/src/semmle/python/Flow.qll +++ b/python/ql/src/semmle/python/Flow.qll @@ -1,7 +1,8 @@ import python private import semmle.python.pointsto.PointsTo -/* Note about matching parent and child nodes and CFG splitting: +/* + * Note about matching parent and child nodes and CFG splitting: * * As a result of CFG splitting a single AST node may have multiple CFG nodes. * Therefore, when matching CFG nodes to children, we need to make sure that @@ -11,7 +12,6 @@ private import semmle.python.pointsto.PointsTo * Vice versa for child nodes that precede the parent. */ - private predicate augstore(ControlFlowNode load, ControlFlowNode store) { exists(Expr load_store | exists(AugAssign aa | aa.getTarget() = load_store) | toAst(load) = load_store and @@ -21,16 +21,14 @@ private predicate augstore(ControlFlowNode load, ControlFlowNode store) { } /** A non-dispatched getNode() to avoid negative recursion issues */ -private AstNode toAst(ControlFlowNode n) { - py_flow_bb_node(n, result, _, _) -} +private AstNode toAst(ControlFlowNode n) { py_flow_bb_node(n, result, _, _) } -/** A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes, +/** + * A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes, * although most syntactic nodes have only one corresponding control flow node. * Edges between control flow nodes include exceptional as well as normal control flow. */ class ControlFlowNode extends @py_flow_node { - /** Whether this control flow node is a load (including those in augmented assignments) */ predicate isLoad() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 3, e) and not augstore(_, this)) @@ -42,24 +40,16 @@ class ControlFlowNode extends @py_flow_node { } /** Whether this control flow node is a delete */ - predicate isDelete() { - exists(Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) - } + predicate isDelete() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) } /** Whether this control flow node is a parameter */ - predicate isParameter() { - exists(Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) - } + predicate isParameter() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) } /** Whether this control flow node is a store in an augmented assignment */ - predicate isAugStore() { - augstore(_, this) - } + predicate isAugStore() { augstore(_, this) } /** Whether this control flow node is a load in an augmented assignment */ - predicate isAugLoad() { - augstore(this, _) - } + predicate isAugLoad() { augstore(this, _) } /** Whether this flow node corresponds to a literal */ predicate isLiteral() { @@ -93,200 +83,141 @@ class ControlFlowNode extends @py_flow_node { } /** Use NameNode.isLoad() instead */ - deprecated predicate isUse() { - toAst(this) instanceof Name and this.isLoad() - } + deprecated predicate isUse() { toAst(this) instanceof Name and this.isLoad() } /** Use NameNode.isStore() */ - deprecated predicate isDefinition() { - toAst(this) instanceof Name and this.isStore() - } + deprecated predicate isDefinition() { toAst(this) instanceof Name and this.isStore() } /** Whether this flow node corresponds to an attribute expression */ - predicate isAttribute() { - toAst(this) instanceof Attribute - } + predicate isAttribute() { toAst(this) instanceof Attribute } /** Use AttrNode.isLoad() instead */ - deprecated predicate isAttributeLoad() { - toAst(this) instanceof Attribute and this.isLoad() - } + deprecated predicate isAttributeLoad() { toAst(this) instanceof Attribute and this.isLoad() } /** Use AttrNode.isStore() instead */ - deprecated predicate isAttributeStore() { - toAst(this) instanceof Attribute and this.isStore() - } + deprecated predicate isAttributeStore() { toAst(this) instanceof Attribute and this.isStore() } /** Whether this flow node corresponds to an subscript expression */ - predicate isSubscript() { - toAst(this) instanceof Subscript - } + predicate isSubscript() { toAst(this) instanceof Subscript } /** Use SubscriptNode.isLoad() instead */ - deprecated predicate isSubscriptLoad() { - toAst(this) instanceof Subscript and this.isLoad() - } + deprecated predicate isSubscriptLoad() { toAst(this) instanceof Subscript and this.isLoad() } /** Use SubscriptNode.isStore() instead */ - deprecated predicate isSubscriptStore() { - toAst(this) instanceof Subscript and this.isStore() - } + deprecated predicate isSubscriptStore() { toAst(this) instanceof Subscript and this.isStore() } /** Whether this flow node corresponds to an import member */ - predicate isImportMember() { - toAst(this) instanceof ImportMember - } + predicate isImportMember() { toAst(this) instanceof ImportMember } /** Whether this flow node corresponds to a call */ - predicate isCall() { - toAst(this) instanceof Call - } + predicate isCall() { toAst(this) instanceof Call } /** Whether this flow node is the first in a module */ - predicate isModuleEntry() { - this.isEntryNode() and toAst(this) instanceof Module - } + predicate isModuleEntry() { this.isEntryNode() and toAst(this) instanceof Module } /** Whether this flow node corresponds to an import */ - predicate isImport() { - toAst(this) instanceof ImportExpr - } + predicate isImport() { toAst(this) instanceof ImportExpr } /** Whether this flow node corresponds to a conditional expression */ - predicate isIfExp() { - toAst(this) instanceof IfExp - } + predicate isIfExp() { toAst(this) instanceof IfExp } /** Whether this flow node corresponds to a function definition expression */ - predicate isFunction() { - toAst(this) instanceof FunctionExpr - } + predicate isFunction() { toAst(this) instanceof FunctionExpr } /** Whether this flow node corresponds to a class definition expression */ - predicate isClass() { - toAst(this) instanceof ClassExpr - } + predicate isClass() { toAst(this) instanceof ClassExpr } /** Gets a predecessor of this flow node */ - ControlFlowNode getAPredecessor() { - this = result.getASuccessor() - } + ControlFlowNode getAPredecessor() { this = result.getASuccessor() } /** Gets a successor of this flow node */ - ControlFlowNode getASuccessor() { - py_successors(this, result) - } + ControlFlowNode getASuccessor() { py_successors(this, result) } /** Gets the immediate dominator of this flow node */ - ControlFlowNode getImmediateDominator() { - py_idoms(this, result) - } + ControlFlowNode getImmediateDominator() { py_idoms(this, result) } /** Gets the syntactic element corresponding to this flow node */ - AstNode getNode() { - py_flow_bb_node(this, result, _, _) - } + AstNode getNode() { py_flow_bb_node(this, result, _, _) } string toString() { - exists(Scope s | s.getEntryNode() = this | - result = "Entry node for " + s.toString() - ) + exists(Scope s | s.getEntryNode() = this | result = "Entry node for " + s.toString()) or - exists(Scope s | s.getANormalExit() = this | - result = "Exit node for " + s.toString() - ) + exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString()) or not exists(Scope s | s.getEntryNode() = this or s.getANormalExit() = this) and result = "ControlFlowNode for " + this.getNode().toString() } /** Gets the location of this ControlFlowNode */ - Location getLocation() { - result = this.getNode().getLocation() - } + Location getLocation() { result = this.getNode().getLocation() } /** Whether this flow node is the first in its scope */ - predicate isEntryNode() { - py_scope_flow(this, _, -1) - } + predicate isEntryNode() { py_scope_flow(this, _, -1) } /** The value that this ControlFlowNode points-to. */ - predicate pointsTo(Value value) { - this.pointsTo(_, value, _) - } + predicate pointsTo(Value value) { this.pointsTo(_, value, _) } /** Gets the value that this ControlFlowNode points-to. */ - Value pointsTo() { - this.pointsTo(_, result, _) - } + Value pointsTo() { this.pointsTo(_, result, _) } /** Gets a value that this ControlFlowNode may points-to. */ - Value inferredValue() { - this.pointsTo(_, result, _) - } + Value inferredValue() { this.pointsTo(_, result, _) } /** The value and origin that this ControlFlowNode points-to. */ - predicate pointsTo(Value value, ControlFlowNode origin) { - this.pointsTo(_, value, origin) - } + predicate pointsTo(Value value, ControlFlowNode origin) { this.pointsTo(_, value, origin) } /** The value and origin that this ControlFlowNode points-to, given the context. */ predicate pointsTo(Context context, Value value, ControlFlowNode origin) { PointsTo::pointsTo(this, context, value, origin) } - /** + /** * Gets what this flow node might "refer-to". Performs a combination of localized (intra-procedural) points-to * analysis and global module-level analysis. This points-to analysis favours precision over recall. It is highly * precise, but may not provide information for a significant number of flow-nodes. * If the class is unimportant then use `refersTo(value)` or `refersTo(value, origin)` instead. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Object obj, ClassObject cls, ControlFlowNode origin) { this.refersTo(_, obj, cls, origin) } /** Gets what this expression might "refer-to" in the given `context`. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Context context, Object obj, ClassObject cls, ControlFlowNode origin) { not obj = unknownValue() and not cls = theUnknownType() and PointsTo::points_to(this, context, obj, cls, origin) } - /** Whether this flow node might "refer-to" to `value` which is from `origin` + /** + * Whether this flow node might "refer-to" to `value` which is from `origin` * Unlike `this.refersTo(value, _, origin)` this predicate includes results * where the class cannot be inferred. */ - pragma [nomagic] + pragma[nomagic] predicate refersTo(Object obj, ControlFlowNode origin) { not obj = unknownValue() and PointsTo::points_to(this, _, obj, _, origin) } /** Equivalent to `this.refersTo(value, _)` */ - predicate refersTo(Object obj) { - this.refersTo(obj, _) - } + predicate refersTo(Object obj) { this.refersTo(obj, _) } /** Gets the basic block containing this flow node */ - BasicBlock getBasicBlock() { - result.contains(this) - } + BasicBlock getBasicBlock() { result.contains(this) } /** Gets the scope containing this flow node */ Scope getScope() { - if this.getNode() instanceof Scope then - /* Entry or exit node */ - result = this.getNode() - else - result = this.getNode().getScope() + if this.getNode() instanceof Scope + then + /* Entry or exit node */ + result = this.getNode() + else result = this.getNode().getScope() } /** Gets the enclosing module */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } /** Gets a successor for this node if the relevant condition is True. */ ControlFlowNode getATrueSuccessor() { @@ -308,19 +239,15 @@ class ControlFlowNode extends @py_flow_node { /** Gets a successor for this node if no exception is raised. */ ControlFlowNode getANormalSuccessor() { - result = this.getASuccessor() and not - py_exception_successors(this, result) + result = this.getASuccessor() and + not py_exception_successors(this, result) } /** Whether the scope may be exited as a result of this node raising an exception */ - predicate isExceptionalExit(Scope s) { - py_scope_flow(this, s, 1) - } + predicate isExceptionalExit(Scope s) { py_scope_flow(this, s, 1) } /** Whether this node is a normal (non-exceptional) exit */ - predicate isNormalExit() { - py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) - } + predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) } /** Whether it is unlikely that this ControlFlowNode can be reached */ predicate unlikelyReachable() { @@ -340,93 +267,81 @@ class ControlFlowNode extends @py_flow_node { ) } - /** Check whether this control-flow node has complete points-to information. + /** + * Check whether this control-flow node has complete points-to information. * This would mean that the analysis managed to infer an over approximation * of possible values at runtime. */ predicate hasCompletePointsToSet() { - ( - // If the tracking failed, then `this` will be its own "origin". In that - // case, we want to exclude nodes for which there is also a different - // origin, as that would indicate that some paths failed and some did not. - this.refersTo(_, _, this) and - not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) - ) or ( - // If `this` is a use of a variable, then we must have complete points-to - // for that variable. - exists(SsaVariable v | v.getAUse() = this | - varHasCompletePointsToSet(v) - ) - ) + // If the tracking failed, then `this` will be its own "origin". In that + // case, we want to exclude nodes for which there is also a different + // origin, as that would indicate that some paths failed and some did not. + this.refersTo(_, _, this) and + not exists(ControlFlowNode other | other != this and this.refersTo(_, _, other)) + or + // If `this` is a use of a variable, then we must have complete points-to + // for that variable. + exists(SsaVariable v | v.getAUse() = this | varHasCompletePointsToSet(v)) } /** Whether this strictly dominates other. */ - pragma [inline] predicate strictlyDominates(ControlFlowNode other) { + pragma[inline] + predicate strictlyDominates(ControlFlowNode other) { // This predicate is gigantic, so it must be inlined. // About 1.4 billion tuples for OpenStack Cinder. this.getBasicBlock().strictlyDominates(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i < j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i < j) } - /** Whether this dominates other. + /** + * Whether this dominates other. * Note that all nodes dominate themselves. */ - pragma [inline] predicate dominates(ControlFlowNode other) { + pragma[inline] + predicate dominates(ControlFlowNode other) { // This predicate is gigantic, so it must be inlined. this.getBasicBlock().strictlyDominates(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i <= j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i <= j) } /** Whether this strictly reaches other. */ - pragma [inline] predicate strictlyReaches(ControlFlowNode other) { + pragma[inline] + predicate strictlyReaches(ControlFlowNode other) { // This predicate is gigantic, even larger than strictlyDominates, // so it must be inlined. this.getBasicBlock().strictlyReaches(other.getBasicBlock()) or - exists(BasicBlock b, int i, int j | - this = b.getNode(i) and other = b.getNode(j) and i < j - ) + exists(BasicBlock b, int i, int j | this = b.getNode(i) and other = b.getNode(j) and i < j) } /* Holds if this CFG node is a branch */ - predicate isBranch() { - py_true_successors(this, _) or py_false_successors(this, _) - } + predicate isBranch() { py_true_successors(this, _) or py_false_successors(this, _) } - ControlFlowNode getAChild() { - result = this.getExprChild(this.getBasicBlock()) - } + ControlFlowNode getAChild() { result = this.getExprChild(this.getBasicBlock()) } /* join-ordering helper for `getAChild() */ - pragma [noinline] + pragma[noinline] private ControlFlowNode getExprChild(BasicBlock dom) { this.getNode().(Expr).getAChildNode() = result.getNode() and result.getBasicBlock().dominates(dom) and not this instanceof UnaryExprNode } - } - -/* This class exists to provide an implementation over ControlFlowNode.getNode() +/* + * This class exists to provide an implementation over ControlFlowNode.getNode() * that subsumes all the others in an way that's obvious to the optimiser. * This avoids wasting time on the trivial overrides on the ControlFlowNode subclasses. */ -private class AnyNode extends ControlFlowNode { - override AstNode getNode() { - result = super.getNode() - } +private class AnyNode extends ControlFlowNode { + override AstNode getNode() { result = super.getNode() } } - -/** Check whether a SSA variable has complete points-to information. +/** + * Check whether a SSA variable has complete points-to information. * This would mean that the analysis managed to infer an overapproximation * of possible values at runtime. */ @@ -449,28 +364,35 @@ private predicate varHasCompletePointsToSet(SsaVariable var) { /** A control flow node corresponding to a call expression, such as `func(...)` */ class CallNode extends ControlFlowNode { - - CallNode() { - toAst(this) instanceof Call - } + CallNode() { toAst(this) instanceof Call } /** Gets the flow node corresponding to the function expression for the call corresponding to this flow node */ ControlFlowNode getFunction() { - exists(Call c | this.getNode() = c and c.getFunc() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c | + this.getNode() = c and + c.getFunc() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to the nth argument of the call corresponding to this flow node */ ControlFlowNode getArg(int n) { - exists(Call c | this.getNode() = c and c.getArg(n) = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c | + this.getNode() = c and + c.getArg(n) = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */ ControlFlowNode getArgByName(string name) { - exists(Call c, Keyword k | this.getNode() = c and k = c.getAKeyword() and - k.getValue() = result.getNode() and k.getArg() = name and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Call c, Keyword k | + this.getNode() = c and + k = c.getAKeyword() and + k.getValue() = result.getNode() and + k.getArg() = name and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the flow node corresponding to an argument of the call corresponding to this flow node */ @@ -489,15 +411,11 @@ class CallNode extends ControlFlowNode { } predicate isClassDecoratorCall() { - exists(ClassExpr cls | - this.getNode() = cls.getADecoratorCall() - ) + exists(ClassExpr cls | this.getNode() = cls.getADecoratorCall()) } predicate isFunctionDecoratorCall() { - exists(FunctionExpr func | - this.getNode() = func.getADecoratorCall() - ) + exists(FunctionExpr func | this.getNode() = func.getADecoratorCall()) } /** Gets the tuple (*) argument of this call, provided there is exactly one. */ @@ -505,60 +423,56 @@ class CallNode extends ControlFlowNode { result.getNode() = this.getNode().getStarArg() and result.getBasicBlock().dominates(this.getBasicBlock()) } - } /** A control flow corresponding to an attribute expression, such as `value.attr` */ class AttrNode extends ControlFlowNode { - AttrNode() { - toAst(this) instanceof Attribute - } + AttrNode() { toAst(this) instanceof Attribute } /** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node */ ControlFlowNode getObject() { - exists(Attribute a | this.getNode() = a and a.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Attribute a | + this.getNode() = a and + a.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Use getObject() instead */ - deprecated ControlFlowNode getValue() { - result = this.getObject() - } + deprecated ControlFlowNode getValue() { result = this.getObject() } /** Use getObject(name) instead */ - deprecated ControlFlowNode getValue(string name) { - result = this.getObject(name) - } + deprecated ControlFlowNode getValue(string name) { result = this.getObject(name) } - /** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node, - * with the matching name */ + /** + * Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node, + * with the matching name + */ ControlFlowNode getObject(string name) { exists(Attribute a | - this.getNode() = a and a.getObject() = result.getNode() and + this.getNode() = a and + a.getObject() = result.getNode() and a.getName() = name and - result.getBasicBlock().dominates(this.getBasicBlock())) + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** Gets the attribute name of the attribute expression corresponding to this flow node */ - string getName() { - exists(Attribute a | this.getNode() = a and a.getName() = result) - } + string getName() { exists(Attribute a | this.getNode() = a and a.getName() = result) } override Attribute getNode() { result = super.getNode() } - } /** A control flow node corresponding to a `from ... import ...` expression */ class ImportMemberNode extends ControlFlowNode { - ImportMemberNode() { - toAst(this) instanceof ImportMember - } + ImportMemberNode() { toAst(this) instanceof ImportMember } - /** Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node, - * with the matching name */ + /** + * Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node, + * with the matching name + */ ControlFlowNode getModule(string name) { - exists(ImportMember i | - this.getNode() = i and i.getModule() = result.getNode() | + exists(ImportMember i | this.getNode() = i and i.getModule() = result.getNode() | i.getName() = name and result.getBasicBlock().dominates(this.getBasicBlock()) ) @@ -567,60 +481,59 @@ class ImportMemberNode extends ControlFlowNode { override ImportMember getNode() { result = super.getNode() } } - /** A control flow node corresponding to an artificial expression representing an import */ class ImportExprNode extends ControlFlowNode { - - ImportExprNode() { - toAst(this) instanceof ImportExpr - } + ImportExprNode() { toAst(this) instanceof ImportExpr } override ImportExpr getNode() { result = super.getNode() } - } /** A control flow node corresponding to a `from ... import *` statement */ class ImportStarNode extends ControlFlowNode { - - ImportStarNode() { - toAst(this) instanceof ImportStar - } + ImportStarNode() { toAst(this) instanceof ImportStar } /** Gets the flow node corresponding to the module in the import-star corresponding to this flow node */ ControlFlowNode getModule() { - exists(ImportStar i | - this.getNode() = i and i.getModuleExpr() = result.getNode() | + exists(ImportStar i | this.getNode() = i and i.getModuleExpr() = result.getNode() | result.getBasicBlock().dominates(this.getBasicBlock()) ) } override ImportStar getNode() { result = super.getNode() } - } /** A control flow node corresponding to a subscript expression, such as `value[slice]` */ class SubscriptNode extends ControlFlowNode { - SubscriptNode() { - toAst(this) instanceof Subscript - } + SubscriptNode() { toAst(this) instanceof Subscript } - /** DEPRECATED: Use `getObject()` instead. - * This will be formally deprecated before the end 2018 and removed in 2019.*/ + /** + * DEPRECATED: Use `getObject()` instead. + * This will be formally deprecated before the end 2018 and removed in 2019. + */ deprecated ControlFlowNode getValue() { - exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** flow node corresponding to the value of the sequence in a subscript operation */ ControlFlowNode getObject() { - exists(Subscript s | this.getNode() = s and s.getObject() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getObject() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } /** flow node corresponding to the index in a subscript operation */ ControlFlowNode getIndex() { - exists(Subscript s | this.getNode() = s and s.getIndex() = result.getNode() and - result.getBasicBlock().dominates(this.getBasicBlock())) + exists(Subscript s | + this.getNode() = s and + s.getIndex() = result.getNode() and + result.getBasicBlock().dominates(this.getBasicBlock()) + ) } override Subscript getNode() { result = super.getNode() } @@ -628,17 +541,18 @@ class SubscriptNode extends ControlFlowNode { /** A control flow node corresponding to a comparison operation, such as `x DeletionNode -> NameNode('b') -> AttrNode('y') -> DeletionNode`. */ class DeletionNode extends ControlFlowNode { - - DeletionNode() { - toAst(this) instanceof Delete - } + DeletionNode() { toAst(this) instanceof Delete } /** Gets the unique target of this deletion node. */ - ControlFlowNode getTarget() { - result.getASuccessor() = this - } - + ControlFlowNode getTarget() { result.getASuccessor() = this } } /** A control flow node corresponding to a sequence (tuple or list) literal */ @@ -806,20 +703,15 @@ abstract class SequenceNode extends ControlFlowNode { } /** Gets the control flow node for an element of this sequence */ - ControlFlowNode getAnElement() { - result = this.getElement(_) - } + ControlFlowNode getAnElement() { result = this.getElement(_) } /** Gets the control flow node for the nth element of this sequence */ abstract ControlFlowNode getElement(int n); - } /** A control flow node corresponding to a tuple expression such as `( 1, 3, 5, 7, 9 )` */ class TupleNode extends SequenceNode { - TupleNode() { - toAst(this) instanceof Tuple - } + TupleNode() { toAst(this) instanceof Tuple } override ControlFlowNode getElement(int n) { exists(Tuple t | this.getNode() = t and result.getNode() = t.getElt(n)) and @@ -833,9 +725,7 @@ class TupleNode extends SequenceNode { /** A control flow node corresponding to a list expression, such as `[ 1, 3, 5, 7, 9 ]` */ class ListNode extends SequenceNode { - ListNode() { - toAst(this) instanceof List - } + ListNode() { toAst(this) instanceof List } override ControlFlowNode getElement(int n) { exists(List l | this.getNode() = l and result.getNode() = l.getElt(n)) and @@ -845,14 +735,10 @@ class ListNode extends SequenceNode { this.getBasicBlock().dominates(result.getBasicBlock()) ) } - } class SetNode extends ControlFlowNode { - - SetNode() { - toAst(this) instanceof Set - } + SetNode() { toAst(this) instanceof Set } ControlFlowNode getAnElement() { exists(Set s | this.getNode() = s and result.getNode() = s.getElt(_)) and @@ -862,17 +748,14 @@ class SetNode extends ControlFlowNode { this.getBasicBlock().dominates(result.getBasicBlock()) ) } - } /** A control flow node corresponding to a dictionary literal, such as `{ 'a': 1, 'b': 2 }` */ class DictNode extends ControlFlowNode { + DictNode() { toAst(this) instanceof Dict } - DictNode() { - toAst(this) instanceof Dict - } - - /** Gets a key of this dictionary literal node, for those items that have keys + /** + * Gets a key of this dictionary literal node, for those items that have keys * E.g, in {'a':1, **b} this returns only 'a' */ ControlFlowNode getAKey() { @@ -880,12 +763,11 @@ class DictNode extends ControlFlowNode { result.getBasicBlock().dominates(this.getBasicBlock()) } - /** Gets a value of this dictionary literal node*/ + /** Gets a value of this dictionary literal node */ ControlFlowNode getAValue() { exists(Dict d | this.getNode() = d and result.getNode() = d.getAValue()) and result.getBasicBlock().dominates(this.getBasicBlock()) } - } private AstNode assigned_value(Expr lhs) { @@ -898,30 +780,31 @@ private AstNode assigned_value(Expr lhs) { /* lhs += x => result = (lhs + x) */ exists(AugAssign a, BinaryExpr b | b = a.getOperation() and result = b and lhs = b.getLeft()) or - /* ..., lhs, ... = ..., result, ... + /* + * ..., lhs, ... = ..., result, ... * or * ..., (..., lhs, ...), ... = ..., (..., result, ...), ... - */ + */ + exists(Assign a | nested_sequence_assign(a.getATarget(), a.getValue(), lhs, result)) or /* for lhs in seq: => `result` is the `for` node, representing the `iter(next(seq))` operation. */ result.(For).getTarget() = lhs } -predicate nested_sequence_assign(Expr left_parent, Expr right_parent, - Expr left_result, Expr right_result) { +predicate nested_sequence_assign( + Expr left_parent, Expr right_parent, Expr left_result, Expr right_result +) { exists(Assign a | a.getATarget().getASubExpression*() = left_parent and a.getValue().getASubExpression*() = right_parent ) and - exists(int i, Expr left_elem, Expr right_elem - | + exists(int i, Expr left_elem, Expr right_elem | ( left_elem = left_parent.(Tuple).getElt(i) or left_elem = left_parent.(List).getElt(i) - ) - and + ) and ( right_elem = right_parent.(Tuple).getElt(i) or @@ -936,10 +819,7 @@ predicate nested_sequence_assign(Expr left_parent, Expr right_parent, /** A flow node for a `for` statement. */ class ForNode extends ControlFlowNode { - - ForNode() { - toAst(this) instanceof For - } + ForNode() { toAst(this) instanceof For } override For getNode() { result = super.getNode() } @@ -954,7 +834,8 @@ class ForNode extends ControlFlowNode { ControlFlowNode getSequence() { exists(For for | toAst(this) = for and - for.getIter() = result.getNode() | + for.getIter() = result.getNode() + | result.getBasicBlock().dominates(this.getBasicBlock()) ) } @@ -974,15 +855,11 @@ class ForNode extends ControlFlowNode { toAst(this) = toAst(result) and this.getBasicBlock().dominates(result.getBasicBlock()) } - } /** A flow node for a `raise` statement */ class RaiseStmtNode extends ControlFlowNode { - - RaiseStmtNode() { - toAst(this) instanceof Raise - } + RaiseStmtNode() { toAst(this) instanceof Raise } /** Gets the control flow node for the exception raised by this raise statement */ ControlFlowNode getException() { @@ -992,14 +869,13 @@ class RaiseStmtNode extends ControlFlowNode { result.getBasicBlock().dominates(this.getBasicBlock()) ) } - } -/** A control flow node corresponding to a (plain variable) name expression, such as `var`. +/** + * A control flow node corresponding to a (plain variable) name expression, such as `var`. * `None`, `True` and `False` are excluded. */ class NameNode extends ControlFlowNode { - NameNode() { exists(Name n | py_flow_bb_node(this, n, _, _)) or @@ -1008,20 +884,21 @@ class NameNode extends ControlFlowNode { /** Whether this flow node defines the variable `v`. */ predicate defines(Variable v) { - exists(Name d | this.getNode() = d and d.defines(v)) - and not this.isLoad() + exists(Name d | this.getNode() = d and d.defines(v)) and + not this.isLoad() } /** Whether this flow node deletes the variable `v`. */ - predicate deletes(Variable v) { - exists(Name d | this.getNode() = d and d.deletes(v)) - } + predicate deletes(Variable v) { exists(Name d | this.getNode() = d and d.deletes(v)) } /** Whether this flow node uses the variable `v`. */ predicate uses(Variable v) { - this.isLoad() and exists(Name u | this.getNode() = u and u.uses(v)) + this.isLoad() and + exists(Name u | this.getNode() = u and u.uses(v)) or - exists(PlaceHolder u | this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Load) + exists(PlaceHolder u | + this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Load + ) or Scopes::use_of_global_variable(this, v.getScope(), v.getId()) } @@ -1033,58 +910,40 @@ class NameNode extends ControlFlowNode { } /** Whether this is a use of a local variable. */ - predicate isLocal() { - Scopes::local(this) - } + predicate isLocal() { Scopes::local(this) } /** Whether this is a use of a non-local variable. */ - predicate isNonLocal() { - Scopes::non_local(this) - } + predicate isNonLocal() { Scopes::non_local(this) } /** Whether this is a use of a global (including builtin) variable. */ - predicate isGlobal() { - Scopes::use_of_global_variable(this, _, _) - } - - predicate isSelf() { - exists(SsaVariable selfvar | - selfvar.isSelf() and selfvar.getAUse() = this - ) - } + predicate isGlobal() { Scopes::use_of_global_variable(this, _, _) } + predicate isSelf() { exists(SsaVariable selfvar | selfvar.isSelf() and selfvar.getAUse() = this) } } /** A control flow node corresponding to a named constant, one of `None`, `True` or `False`. */ class NameConstantNode extends NameNode { + NameConstantNode() { exists(NameConstant n | py_flow_bb_node(this, n, _, _)) } - NameConstantNode() { - exists(NameConstant n | py_flow_bb_node(this, n, _, _)) - } + deprecated override predicate defines(Variable v) { none() } - override deprecated predicate defines(Variable v) { none() } - - override deprecated predicate deletes(Variable v) { none() } - - /* We ought to override uses as well, but that has + deprecated override predicate deletes(Variable v) { none() } + /* + * We ought to override uses as well, but that has * a serious performance impact. - deprecated predicate uses(Variable v) { none() } - */ -} + * deprecated predicate uses(Variable v) { none() } + */ + + } /** A control flow node correspoinding to a starred expression, `*a`. */ class StarredNode extends ControlFlowNode { - StarredNode() { - toAst(this) instanceof Starred - } + StarredNode() { toAst(this) instanceof Starred } - ControlFlowNode getValue() { - toAst(result) = toAst(this).(Starred).getValue() - } + ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() } } private module Scopes { - private predicate fast_local(NameNode n) { exists(FastLocalVariable v | n.uses(v) and @@ -1110,29 +969,24 @@ private module Scopes { } // magic is fine, but we get questionable join-ordering of it - pragma [nomagic] + pragma[nomagic] predicate use_of_global_variable(NameNode n, Module scope, string name) { n.isLoad() and - not non_local(n) - and - not exists(SsaVariable var | - var.getAUse() = n | - var.getVariable() instanceof FastLocalVariable + not non_local(n) and + not exists(SsaVariable var | var.getAUse() = n | + var.getVariable() instanceof FastLocalVariable or n.getScope() instanceof Class and not maybe_undefined(var) - ) - and name = n.getId() - and scope = n.getEnclosingModule() + ) and + name = n.getId() and + scope = n.getEnclosingModule() } private predicate maybe_defined(SsaVariable var) { exists(var.getDefinition()) and not py_ssa_phi(var, _) and not var.getDefinition().isDelete() or - exists(SsaVariable input | - input = var.getAPhiInput() | - maybe_defined(input) - ) + exists(SsaVariable input | input = var.getAPhiInput() | maybe_defined(input)) } private predicate maybe_undefined(SsaVariable var) { @@ -1143,61 +997,52 @@ private module Scopes { maybe_undefined(var.getAPhiInput()) or exists(BasicBlock incoming | - exists(var.getAPhiInput()) and + exists(var.getAPhiInput()) and incoming.getASuccessor() = var.getDefinition().getBasicBlock() and not var.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming) ) } - } /** A basic block (ignoring exceptional flow edges to scope exit) */ class BasicBlock extends @py_flow_node { - - BasicBlock() { - py_flow_bb_node(_, _, this, _) - } + BasicBlock() { py_flow_bb_node(_, _, this, _) } /** Whether this basic block contains the specified node */ - predicate contains(ControlFlowNode node) { - py_flow_bb_node(node, _, this, _) - } + predicate contains(ControlFlowNode node) { py_flow_bb_node(node, _, this, _) } /** Gets the nth node in this basic block */ - ControlFlowNode getNode(int n) { - py_flow_bb_node(result, _, this, n) - } + ControlFlowNode getNode(int n) { py_flow_bb_node(result, _, this, n) } - string toString() { - result = "BasicBlock" - } + string toString() { result = "BasicBlock" } /** Whether this basic block strictly dominates the other */ - pragma[nomagic] predicate strictlyDominates(BasicBlock other) { - other.getImmediateDominator+() = this - } + pragma[nomagic] + predicate strictlyDominates(BasicBlock other) { other.getImmediateDominator+() = this } /** Whether this basic block dominates the other */ - pragma[nomagic] predicate dominates(BasicBlock other) { + pragma[nomagic] + predicate dominates(BasicBlock other) { this = other or this.strictlyDominates(other) } - cached BasicBlock getImmediateDominator() { + cached + BasicBlock getImmediateDominator() { this.firstNode().getImmediateDominator().getBasicBlock() = result } - /** Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor - * of `other` but does not strictly dominate `other` */ + /** + * Dominance frontier of a node x is the set of all nodes `other` such that `this` dominates a predecessor + * of `other` but does not strictly dominate `other` + */ pragma[noinline] predicate dominanceFrontier(BasicBlock other) { this.dominates(other.getAPredecessor()) and not this.strictlyDominates(other) } - private ControlFlowNode firstNode() { - result = this - } + private ControlFlowNode firstNode() { result = this } /** Gets the last node in this basic block */ ControlFlowNode getLastNode() { @@ -1207,33 +1052,25 @@ class BasicBlock extends @py_flow_node { ) } - private predicate oneNodeBlock() { - this.firstNode() = this.getLastNode() - } + private predicate oneNodeBlock() { this.firstNode() = this.getLastNode() } private predicate startLocationInfo(string file, int line, int col) { - if this.firstNode().getNode() instanceof Scope then - this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _) - else - this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _) + if this.firstNode().getNode() instanceof Scope + then this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _) + else this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _) } private predicate endLocationInfo(int endl, int endc) { - if (this.getLastNode().getNode() instanceof Scope and not this.oneNodeBlock()) then - this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc) - else - this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc) + if this.getLastNode().getNode() instanceof Scope and not this.oneNodeBlock() + then this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc) + else this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc) } /** Gets a successor to this basic block */ - BasicBlock getASuccessor() { - result = this.getLastNode().getASuccessor().getBasicBlock() - } + BasicBlock getASuccessor() { result = this.getLastNode().getASuccessor().getBasicBlock() } /** Gets a predecessor to this basic block */ - BasicBlock getAPredecessor() { - result.getASuccessor() = this - } + BasicBlock getAPredecessor() { result.getASuccessor() = this } /** Whether flow from this basic block reaches a normal exit from its scope */ predicate reachesExit() { @@ -1243,15 +1080,12 @@ class BasicBlock extends @py_flow_node { } predicate hasLocationInfo(string file, int line, int col, int endl, int endc) { - this.startLocationInfo(file, line, col) - and + this.startLocationInfo(file, line, col) and this.endLocationInfo(endl, endc) } /** Gets a true successor to this basic block */ - BasicBlock getATrueSuccessor() { - result = this.getLastNode().getATrueSuccessor().getBasicBlock() - } + BasicBlock getATrueSuccessor() { result = this.getLastNode().getATrueSuccessor().getBasicBlock() } /** Gets a false successor to this basic block */ BasicBlock getAFalseSuccessor() { @@ -1271,9 +1105,9 @@ class BasicBlock extends @py_flow_node { } /** Gets the scope of this block */ - pragma [nomagic] Scope getScope() { - exists(ControlFlowNode n | - n.getBasicBlock() = this | + pragma[nomagic] + Scope getScope() { + exists(ControlFlowNode n | n.getBasicBlock() = this | /* Take care not to use an entry or exit node as that node's scope will be the outer scope */ not py_scope_flow(n, _, -1) and not py_scope_flow(n, _, 0) and @@ -1284,7 +1118,8 @@ class BasicBlock extends @py_flow_node { ) } - /** Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. + /** + * Whether (as inferred by type inference) it is highly unlikely (or impossible) for control to flow from this to succ. */ predicate unlikelySuccessor(BasicBlock succ) { this.getLastNode().(RaisingNode).unlikelySuccessor(succ.firstNode()) @@ -1293,22 +1128,18 @@ class BasicBlock extends @py_flow_node { } /** Holds if this basic block strictly reaches the other. Is the start of other reachable from the end of this. */ - predicate strictlyReaches(BasicBlock other) { - this.getASuccessor+() = other - } + predicate strictlyReaches(BasicBlock other) { this.getASuccessor+() = other } /** Holds if this basic block reaches the other. Is the start of other reachable from the end of this. */ - predicate reaches(BasicBlock other) { - this = other or this.strictlyReaches(other) - } + predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) } - /** Whether (as inferred by type inference) this basic block is likely to be reachable. + /** + * Whether (as inferred by type inference) this basic block is likely to be reachable. */ - predicate likelyReachable() { - start_bb_likely_reachable(this) - } + predicate likelyReachable() { start_bb_likely_reachable(this) } - /** Gets the `ConditionBlock`, if any, that controls this block and + /** + * Gets the `ConditionBlock`, if any, that controls this block and * does not control any other `ConditionBlock`s that control this block. * That is the `ConditionBlock` that is closest dominator. */ @@ -1321,22 +1152,17 @@ class BasicBlock extends @py_flow_node { not result.(ConditionBlock).controls(this, _) } - /** Holds if flow from this BasicBlock always reaches `succ` + /** + * Holds if flow from this BasicBlock always reaches `succ` */ predicate alwaysReaches(BasicBlock succ) { succ = this or - strictcount(this.getASuccessor()) = 1 - and succ = this.getASuccessor() + strictcount(this.getASuccessor()) = 1 and + succ = this.getASuccessor() or - forex(BasicBlock immsucc | - immsucc = this.getASuccessor() - | - immsucc.alwaysReaches(succ) - ) - + forex(BasicBlock immsucc | immsucc = this.getASuccessor() | immsucc.alwaysReaches(succ)) } - } private predicate start_bb_likely_reachable(BasicBlock b) { @@ -1358,6 +1184,3 @@ private predicate end_bb_likely_reachable(BasicBlock b) { not p = b.getLastNode() ) } - - - diff --git a/python/ql/src/semmle/python/Function.qll b/python/ql/src/semmle/python/Function.qll index 832a9121176..3bf991b313e 100644 --- a/python/ql/src/semmle/python/Function.qll +++ b/python/ql/src/semmle/python/Function.qll @@ -1,43 +1,37 @@ import python -/** +/** * A function, independent of defaults and binding. - * It is the syntactic entity that is compiled to a code object. + * It is the syntactic entity that is compiled to a code object. */ class Function extends Function_, Scope, AstNode { - /** The expression defining this function */ - CallableExpr getDefinition() { - result = this.getParent() - } + CallableExpr getDefinition() { result = this.getParent() } - /** The scope in which this function occurs, will be a class for a method, - * another function for nested functions, generator expressions or comprehensions, - * or a module for a plain function. */ - override Scope getEnclosingScope() { - result = this.getParent().(Expr).getScope() - } + /** + * The scope in which this function occurs, will be a class for a method, + * another function for nested functions, generator expressions or comprehensions, + * or a module for a plain function. + */ + override Scope getEnclosingScope() { result = this.getParent().(Expr).getScope() } - override Scope getScope() { - result = this.getEnclosingScope() - } + override Scope getScope() { result = this.getEnclosingScope() } /** Whether this function is declared in a class */ - predicate isMethod() { - exists(Class cls | this.getEnclosingScope() = cls) - } + predicate isMethod() { exists(Class cls | this.getEnclosingScope() = cls) } /** Whether this is a special method, that is does its name have the form `__xxx__` (except `__init__`) */ predicate isSpecialMethod() { this.isMethod() and exists(string name | this.getName() = name | name.matches("\\_\\_%\\_\\_") and - name != "__init__") + name != "__init__" + ) } - /** + /** * Whether this function is a generator function, - * that is whether it contains a yield or yield-from expression + * that is whether it contains a yield or yield-from expression */ predicate isGenerator() { exists(Yield y | y.getScope() = this) @@ -46,88 +40,63 @@ class Function extends Function_, Scope, AstNode { } /** Whether this function is declared in a class and is named `__init__` */ - predicate isInitMethod() { - this.isMethod() and this.getName() = "__init__" - } + predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" } /** Gets a decorator of this function */ - Expr getADecorator() { - result = ((FunctionExpr)this.getDefinition()).getADecorator() - } + Expr getADecorator() { result = this.getDefinition().(FunctionExpr).getADecorator() } /** Gets the name of the nth argument (for simple arguments) */ - string getArgName(int index) { - result = ((Name)this.getArg(index)).getId() - } + string getArgName(int index) { result = this.getArg(index).(Name).getId() } Parameter getArgByName(string name) { result = this.getAnArg() and result.(Name).getId() = name } - override Location getLocation() { - py_scope_location(result, this) - } + override Location getLocation() { py_scope_location(result, this) } - override string toString() { - result = "Function " + this.getName() - } + override string toString() { result = "Function " + this.getName() } /** Gets the statements forming the body of this function */ - override StmtList getBody() { - result = Function_.super.getBody() - } + override StmtList getBody() { result = Function_.super.getBody() } /** Gets the nth statement in the function */ - override Stmt getStmt(int index) { - result = Function_.super.getStmt(index) - } + override Stmt getStmt(int index) { result = Function_.super.getStmt(index) } /** Gets a statement in the function */ - override Stmt getAStmt() { - result = Function_.super.getAStmt() - } + override Stmt getAStmt() { result = Function_.super.getAStmt() } /** Gets the name used to define this function */ - override string getName() { - result = Function_.super.getName() - } + override string getName() { result = Function_.super.getName() } /** Gets the metrics for this function */ - FunctionMetrics getMetrics() { - result = this - } + FunctionMetrics getMetrics() { result = this } /** Gets the FunctionObject corresponding to this function */ - FunctionObject getFunctionObject() { - result.getOrigin() = this.getDefinition() - } + FunctionObject getFunctionObject() { result.getOrigin() = this.getDefinition() } - /** Whether this function is a procedure, that is, it has no explicit return statement and always returns None. - * Note that generator and async functions are not procedures as they return generators and coroutines respectively. */ + /** + * Whether this function is a procedure, that is, it has no explicit return statement and always returns None. + * Note that generator and async functions are not procedures as they return generators and coroutines respectively. + */ predicate isProcedure() { - not exists(this.getReturnNode()) and exists(this.getFallthroughNode()) and not this.isGenerator() and not this.isAsync() + not exists(this.getReturnNode()) and + exists(this.getFallthroughNode()) and + not this.isGenerator() and + not this.isAsync() } /** Gets the number of positional parameters */ - int getPositionalParameterCount() { - result = count(this.getAnArg()) - } + int getPositionalParameterCount() { result = count(this.getAnArg()) } /** Gets the number of keyword-only parameters */ - int getKeywordOnlyParameterCount() { - result = count(this.getAKwonlyarg()) - } + int getKeywordOnlyParameterCount() { result = count(this.getAKwonlyarg()) } /** Whether this function accepts a variable number of arguments. That is, whether it has a starred (*arg) parameter. */ - predicate hasVarArg() { - exists(this.getVararg()) - } + predicate hasVarArg() { exists(this.getVararg()) } /** Whether this function accepts arbitrary keyword arguments. That is, whether it has a double-starred (**kwarg) parameter. */ - predicate hasKwArg() { - exists(this.getKwarg()) - } + predicate hasKwArg() { exists(this.getKwarg()) } override AstNode getAChildNode() { result = this.getAStmt() or @@ -136,7 +105,8 @@ class Function extends Function_, Scope, AstNode { result = this.getKwarg() } - /** Gets the qualified name for this function. + /** + * Gets the qualified name for this function. * Should return the same name as the `__qualname__` attribute on functions in Python 3. */ string getQualifiedName() { @@ -145,38 +115,30 @@ class Function extends Function_, Scope, AstNode { exists(string enclosing_name | enclosing_name = this.getEnclosingScope().(Function).getQualifiedName() or - enclosing_name = this.getEnclosingScope().(Class).getQualifiedName() | + enclosing_name = this.getEnclosingScope().(Class).getQualifiedName() + | result = enclosing_name + "." + this.getName() ) } /** Gets the nth keyword-only parameter of this function. */ - Name getKeywordOnlyArg(int n) { - result = Function_.super.getKwonlyarg(n) - } + Name getKeywordOnlyArg(int n) { result = Function_.super.getKwonlyarg(n) } /** Gets a keyword-only parameter of this function. */ - Name getAKeywordOnlyArg() { - result = this.getKeywordOnlyArg(_) - } + Name getAKeywordOnlyArg() { result = this.getKeywordOnlyArg(_) } override Scope getEvaluatingScope() { - major_version() = 2 and exists(Comp comp | comp.getFunction() = this | result = comp.getEvaluatingScope()) + major_version() = 2 and + exists(Comp comp | comp.getFunction() = this | result = comp.getEvaluatingScope()) or not exists(Comp comp | comp.getFunction() = this) and result = this - or + or major_version() = 3 and result = this } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } /** Gets a control flow node for a return value of this function */ ControlFlowNode getAReturnValueFlowNode() { @@ -185,48 +147,36 @@ class Function extends Function_, Scope, AstNode { ret.getValue() = result.getNode() ) } - } /** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */ class FunctionDef extends Assign { - /* syntax: def name(...): ... */ - FunctionDef() { /* This is an artificial assignment the rhs of which is a (possibly decorated) FunctionExpr */ exists(FunctionExpr f | this.getValue() = f or this.getValue() = f.getADecoratorCall()) } - override string toString() { - result = "FunctionDef" - } + override string toString() { result = "FunctionDef" } /** Gets the function for this statement */ Function getDefinedFunction() { exists(FunctionExpr func | this.containsInScope(func) and result = func.getInnerScope()) } - override Stmt getLastStatement() { - result = this.getDefinedFunction().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getDefinedFunction().getLastStatement() } } class FastLocalsFunction extends Function { - /** A function that uses 'fast' locals, stored in the frame not in a dictionary. */ - FastLocalsFunction () { - not exists(ImportStar i | i.getScope() = this) - and + FastLocalsFunction() { + not exists(ImportStar i | i.getScope() = this) and not exists(Exec e | e.getScope() = this) } - } /** A parameter. Either a Tuple or a Name (always a Name for Python 3) */ class Parameter extends Parameter_ { - Parameter() { /* Parameter_ is just defined as a Name or Tuple, narrow to actual parameters */ exists(ParameterList pl | py_exprs(this, _, pl, _)) @@ -245,36 +195,29 @@ class Parameter extends Parameter_ { } /** Gets this parameter if it is a Name (not a Tuple) */ - Name asName() { - result = this - } + Name asName() { result = this } /** Gets this parameter if it is a Tuple (not a Name) */ - Tuple asTuple() { - result = this - } + Tuple asTuple() { result = this } /** Gets the expression for the default value of this parameter */ Expr getDefault() { - exists(Function f, int n, int c, int d, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, int n, int c, int d, Arguments args | args = f.getDefinition().getArgs() | f.getArg(n) = this and c = count(f.getAnArg()) and d = count(args.getADefault()) and - result = args.getDefault(d-c+n) + result = args.getDefault(d - c + n) ) } /** Gets the annotation expression of this parameter */ Expr getAnnotation() { - exists(Function f, int n, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, int n, Arguments args | args = f.getDefinition().getArgs() | f.getArg(n) = this and result = args.getAnnotation(n) ) or - exists(Function f, Arguments args | - args = f.getDefinition().getArgs() | + exists(Function f, Arguments args | args = f.getDefinition().getArgs() | f.getKwarg() = this and result = args.getKwargannotation() or @@ -283,21 +226,13 @@ class Parameter extends Parameter_ { ) } - Variable getVariable() { - result.getAnAccess() = this.asName() - } + Variable getVariable() { result.getAnAccess() = this.asName() } /** Gets the position of this parameter */ - int getPosition() { - exists(Function f | - f.getArg(result) = this - ) - } + int getPosition() { exists(Function f | f.getArg(result) = this) } /** Gets the name of this parameter */ - string getName() { - result = this.asName().getId() - } + string getName() { result = this.asName().getId() } /** Holds if this parameter is the first parameter of a method. It is not necessarily called "self" */ predicate isSelf() { @@ -307,45 +242,39 @@ class Parameter extends Parameter_ { ) } - /** Holds if this parameter is a 'varargs' parameter. + /** + * Holds if this parameter is a 'varargs' parameter. * The `varargs` in `f(a, b, *varargs)`. */ - predicate isVarargs() { - exists(Function func | func.getVararg() = this) - } + predicate isVarargs() { exists(Function func | func.getVararg() = this) } - /** Holds if this parameter is a 'kwargs' parameter. + /** + * Holds if this parameter is a 'kwargs' parameter. * The `kwargs` in `f(a, b, **kwargs)`. */ - predicate isKwargs() { - exists(Function func | func.getKwarg() = this) - } - + predicate isKwargs() { exists(Function func | func.getKwarg() = this) } } /** An expression that generates a callable object, either a function expression or a lambda */ abstract class CallableExpr extends Expr { - - /** Gets the parameters of this callable. - * This predicate is called getArgs(), rather than getParameters() for compatibility with Python's AST module. */ + /** + * Gets the parameters of this callable. + * This predicate is called getArgs(), rather than getParameters() for compatibility with Python's AST module. + */ abstract Arguments getArgs(); /** Gets the function scope of this code expression. */ abstract Function getInnerScope(); - } /** An (artificial) expression corresponding to a function definition. */ class FunctionExpr extends FunctionExpr_, CallableExpr { - override Expr getASubExpression() { result = this.getArgs().getASubExpression() or result = this.getReturns() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } Call getADecoratorCall() { result.getArg(0) = this or @@ -353,9 +282,7 @@ class FunctionExpr extends FunctionExpr_, CallableExpr { } /** Gets a decorator of this function expression */ - Expr getADecorator() { - result = this.getADecoratorCall().getFunc() - } + Expr getADecorator() { result = this.getADecoratorCall().getFunc() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -363,47 +290,32 @@ class FunctionExpr extends FunctionExpr_, CallableExpr { result = this.getInnerScope() } - override Function getInnerScope() { - result = FunctionExpr_.super.getInnerScope() - } - - override Arguments getArgs() { - result = FunctionExpr_.super.getArgs() - } + override Function getInnerScope() { result = FunctionExpr_.super.getInnerScope() } + override Arguments getArgs() { result = FunctionExpr_.super.getArgs() } } -/** A lambda expression, such as lambda x:x*x */ +/** A lambda expression, such as lambda x:x*x */ class Lambda extends Lambda_, CallableExpr { - /** Gets the expression to the right of the colon in this lambda expression */ Expr getExpression() { - exists(Return ret | ret = this.getInnerScope().getStmt(0) | - result = ret.getValue()) + exists(Return ret | ret = this.getInnerScope().getStmt(0) | result = ret.getValue()) } - override Expr getASubExpression() { - result = this.getArgs().getASubExpression() - } + override Expr getASubExpression() { result = this.getArgs().getASubExpression() } override AstNode getAChildNode() { result = this.getASubExpression() or result = this.getInnerScope() } - override Function getInnerScope() { - result = Lambda_.super.getInnerScope() - } - - override Arguments getArgs() { - result = Lambda_.super.getArgs() - } + override Function getInnerScope() { result = Lambda_.super.getInnerScope() } + override Arguments getArgs() { result = Lambda_.super.getArgs() } } /** The arguments in a function definition */ class Arguments extends Arguments_ { - Expr getASubExpression() { result = this.getAKwDefault() or result = this.getAnAnnotation() or @@ -412,5 +324,3 @@ class Arguments extends Arguments_ { result = this.getADefault() } } - - diff --git a/python/ql/src/semmle/python/GuardedControlFlow.qll b/python/ql/src/semmle/python/GuardedControlFlow.qll index b7caa192f51..0675f336828 100644 --- a/python/ql/src/semmle/python/GuardedControlFlow.qll +++ b/python/ql/src/semmle/python/GuardedControlFlow.qll @@ -2,9 +2,10 @@ import python /** A basic block which terminates in a condition, splitting the subsequent control flow */ class ConditionBlock extends BasicBlock { - ConditionBlock() { - exists(ControlFlowNode succ | succ = this.getATrueSuccessor() or succ = this.getAFalseSuccessor()) + exists(ControlFlowNode succ | + succ = this.getATrueSuccessor() or succ = this.getAFalseSuccessor() + ) } /** Basic blocks controlled by this condition, i.e. those BBs for which the condition is testIsTrue */ @@ -13,12 +14,12 @@ class ConditionBlock extends BasicBlock { * For this block to control the block 'controlled' with 'testIsTrue' the following must be true: * Execution must have passed through the test i.e. 'this' must strictly dominate 'controlled'. * Execution must have passed through the 'testIsTrue' edge leaving 'this'. - * + * * Although "passed through the true edge" implies that this.getATrueSuccessor() dominates 'controlled', * the reverse is not true, as flow may have passed through another edge to get to this.getATrueSuccessor() - * so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that + * so we need to assert that this.getATrueSuccessor() dominates 'controlled' *and* that * all predecessors of this.getATrueSuccessor() are either this or dominated by this.getATrueSuccessor(). - * + * * For example, in the following python snippet: * * if x: @@ -26,7 +27,7 @@ class ConditionBlock extends BasicBlock { * false_successor * uncontrolled * - * false_successor dominates uncontrolled, but not all of its predecessors are this (if x) + * false_successor dominates uncontrolled, but not all of its predecessors are this (if x) * or dominated by itself. Whereas in the following code: * * if x: @@ -35,22 +36,21 @@ class ConditionBlock extends BasicBlock { * false_successor * uncontrolled * - * the block 'while controlled' is controlled because all of its predecessors are this (if x) + * the block 'while controlled' is controlled because all of its predecessors are this (if x) * or (in the case of 'also_controlled') dominated by itself. - * + * * The additional constraint on the predecessors of the test successor implies * that `this` strictly dominates `controlled` so that isn't necessary to check * directly. */ - exists(BasicBlock succ | + + exists(BasicBlock succ | testIsTrue = true and succ = this.getATrueSuccessor() or testIsTrue = false and succ = this.getAFalseSuccessor() - | - succ.dominates(controlled) and - forall(BasicBlock pred | pred.getASuccessor() = succ | - pred = this or succ.dominates(pred) - ) + | + succ.dominates(controlled) and + forall(BasicBlock pred | pred.getASuccessor() = succ | pred = this or succ.dominates(pred)) ) } @@ -58,11 +58,11 @@ class ConditionBlock extends BasicBlock { predicate controlsEdge(BasicBlock pred, BasicBlock succ, boolean testIsTrue) { this.controls(pred, testIsTrue) and succ = pred.getASuccessor() or - pred = this and ( + pred = this and + ( testIsTrue = true and succ = this.getATrueSuccessor() or testIsTrue = false and succ = this.getAFalseSuccessor() ) } - } diff --git a/python/ql/src/semmle/python/Import.qll b/python/ql/src/semmle/python/Import.qll index 1b9b2aed6f4..4e52d08dc68 100644 --- a/python/ql/src/semmle/python/Import.qll +++ b/python/ql/src/semmle/python/Import.qll @@ -1,14 +1,12 @@ import python private import semmle.python.types.Builtins -/** An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial; - * `import x` is transformed into `import x as x` */ +/** + * An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial; + * `import x` is transformed into `import x as x` + */ class Alias extends Alias_ { - - Location getLocation() { - result = this.getValue().getLocation() - } - + Location getLocation() { result = this.getValue().getLocation() } } private predicate valid_module_name(string name) { @@ -19,37 +17,34 @@ private predicate valid_module_name(string name) { /** An artificial expression representing an import */ class ImportExpr extends ImportExpr_ { - - private string basePackageName(int n) { n = 1 and result = this.getEnclosingModule().getPackageName() - or - exists(string bpnm1 | bpnm1 = this.basePackageName(n-1) and + or + exists(string bpnm1 | + bpnm1 = this.basePackageName(n - 1) and bpnm1.matches("%.%") and result = bpnm1.regexpReplaceAll("\\.[^.]*$", "") ) } private predicate implicitRelativeImportsAllowed() { - // relative imports are no longer allowed in Python 3 + // relative imports are no longer allowed in Python 3 major_version() < 3 and // and can be explicitly turned off in later versions of Python 2 not getEnclosingModule().hasFromFuture("absolute_import") } - /** The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports, - * and level > 0 for explicit relative imports. */ + /** + * The language specifies level as -1 if relative imports are to be tried first, 0 for absolute imports, + * and level > 0 for explicit relative imports. + */ override int getLevel() { exists(int l | l = super.getLevel() | l > 0 and result = l or /* The extractor may set level to 0 even though relative imports apply */ - l = 0 and ( - if this.implicitRelativeImportsAllowed() then - result = -1 - else - result = 0 - ) + l = 0 and + (if this.implicitRelativeImportsAllowed() then result = -1 else result = 0) ) } @@ -64,49 +59,47 @@ class ImportExpr extends ImportExpr_ { } private string qualifiedTopName() { - if (this.getLevel() <= 0) then ( - result = this.getTopName() - ) else ( + if this.getLevel() <= 0 + then result = this.getTopName() + else ( result = basePackageName(this.getLevel()) and valid_module_name(result) ) } - /** Gets the name by which the lowest level module or package is imported. - * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + /** + * Gets the name by which the lowest level module or package is imported. + * NOTE: This is the name that used to import the module, + * which may not be the name of the module. + */ string bottomModuleName() { result = relativeTopName() + this.remainderOfName() or - ( - not exists(relativeTopName()) and - result = this.qualifiedTopName() + this.remainderOfName() - ) + not exists(relativeTopName()) and + result = this.qualifiedTopName() + this.remainderOfName() } /** Gets the name of topmost module or package being imported */ string topModuleName() { result = relativeTopName() or - ( - not exists(relativeTopName()) and - result = this.qualifiedTopName() - ) + not exists(relativeTopName()) and + result = this.qualifiedTopName() } - /** Gets the full name of the module resulting from evaluating this import. + /** + * Gets the full name of the module resulting from evaluating this import. * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + * which may not be the name of the module. + */ string getImportedModuleName() { exists(string bottomName | bottomName = this.bottomModuleName() | - if this.isTop() then - result = topModuleName() - else - result = bottomName + if this.isTop() then result = topModuleName() else result = bottomName ) } - /** Gets the names of the modules that may be imported by this import. + /** + * Gets the names of the modules that may be imported by this import. * For example this predicate would return 'x' and 'x.y' for `import x.y` */ string getAnImportedModuleName() { @@ -115,26 +108,24 @@ class ImportExpr extends ImportExpr_ { result = this.getAnImportedModuleName().regexpReplaceAll("\\.[^.]*$", "") } - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } - override predicate hasSideEffects() { - any() - } + override predicate hasSideEffects() { any() } - private string getTopName() { - result = this.getName().regexpReplaceAll("\\..*", "") - } + private string getTopName() { result = this.getName().regexpReplaceAll("\\..*", "") } private string remainderOfName() { - not exists(this.getName()) and result = "" or - this.getLevel() <= 0 and result = this.getName().regexpReplaceAll("^[^\\.]*", "") or + not exists(this.getName()) and result = "" + or + this.getLevel() <= 0 and result = this.getName().regexpReplaceAll("^[^\\.]*", "") + or this.getLevel() > 0 and result = "." + this.getName() } - /** Whether this import is relative, that is not absolute. - * See https://www.python.org/dev/peps/pep-0328/ */ + /** + * Whether this import is relative, that is not absolute. + * See https://www.python.org/dev/peps/pep-0328/ + */ predicate isRelative() { /* Implicit */ exists(this.relativeTopName()) @@ -142,24 +133,22 @@ class ImportExpr extends ImportExpr_ { /* Explicit */ this.getLevel() > 0 } - } /** A `from ... import ...` expression */ class ImportMember extends ImportMember_ { - - override Expr getASubExpression() { - result = this.getModule() - } + override Expr getASubExpression() { result = this.getModule() } override predicate hasSideEffects() { /* Strictly this only has side-effects if the module is a package */ any() } - /** Gets the full name of the module resulting from evaluating this import. - * NOTE: This is the name that used to import the module, - * which may not be the name of the module. */ + /** + * Gets the full name of the module resulting from evaluating this import. + * NOTE: This is the name that used to import the module, + * which may not be the name of the module. + */ string getImportedModuleName() { result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName() } @@ -169,26 +158,22 @@ class ImportMember extends ImportMember_ { /** An import statement */ class Import extends Import_ { - /* syntax: import modname */ - private ImportExpr getAModuleExpr() { result = this.getAName().getValue() - or - result = ((ImportMember)this.getAName().getValue()).getModule() + or + result = this.getAName().getValue().(ImportMember).getModule() } - /** Use getAnImportedModuleName(), + /** + * Use getAnImportedModuleName(), * possibly combined with ModuleObject.importedAs() - * Gets a module imported by this import statement */ - deprecated Module getAModule() { - result.getName() = this.getAnImportedModuleName() - } + * Gets a module imported by this import statement + */ + deprecated Module getAModule() { result.getName() = this.getAnImportedModuleName() } /** Whether this a `from ... import ...` statement */ - predicate isFromImport() { - this.getAName().getValue() instanceof ImportMember - } + predicate isFromImport() { this.getAName().getValue() instanceof ImportMember } override Expr getASubExpression() { result = this.getAModuleExpr() or @@ -196,73 +181,61 @@ class Import extends Import_ { result = this.getAName().getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } - /** Gets the name of an imported module. + /** + * Gets the name of an imported module. * For example, for the import statement `import bar` which * is a relative import in package "foo", this would return * "foo.bar". - * The import statment `from foo import bar` would return + * The import statment `from foo import bar` would return * `foo` and `foo.bar` - * */ + */ string getAnImportedModuleName() { result = this.getAModuleExpr().getAnImportedModuleName() or exists(ImportMember m, string modname | m = this.getAName().getValue() and - modname = m.getModule().(ImportExpr).getImportedModuleName() | + modname = m.getModule().(ImportExpr).getImportedModuleName() + | result = modname or result = modname + "." + m.getName() ) } - } /** An import * statement */ class ImportStar extends ImportStar_ { - /* syntax: from modname import * */ - ImportExpr getModuleExpr() { result = this.getModule() or - result = ((ImportMember)this.getModule()).getModule() + result = this.getModule().(ImportMember).getModule() } - override string toString() { - result = "from " + this.getModuleExpr().getName() + " import *" - } + override string toString() { result = "from " + this.getModuleExpr().getName() + " import *" } - /** Use getAnImportedModuleName(), + /** + * Use getAnImportedModuleName(), * possibly combined with ModuleObject.importedAs() - * Gets the module imported by this import * statement + * Gets the module imported by this import * statement */ - deprecated Module getTheModule() { - result.getName() = this.getImportedModuleName() - } + deprecated Module getTheModule() { result.getName() = this.getImportedModuleName() } - override Expr getASubExpression() { - result = this.getModule() - } + override Expr getASubExpression() { result = this.getModule() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } /** Gets the name of the imported module. */ - string getImportedModuleName() { - result = this.getModuleExpr().getImportedModuleName() - } - + string getImportedModuleName() { result = this.getModuleExpr().getImportedModuleName() } } -/** A statement that imports a module. This can be any statement that includes the `import` keyword, - * such as `import sys`, `from sys import version` or `from sys import *`. */ +/** + * A statement that imports a module. This can be any statement that includes the `import` keyword, + * such as `import sys`, `from sys import version` or `from sys import *`. + */ class ImportingStmt extends Stmt { - ImportingStmt() { this instanceof Import or @@ -271,9 +244,8 @@ class ImportingStmt extends Stmt { /** Gets the name of an imported module. */ string getAnImportedModuleName() { - result = this.(Import).getAnImportedModuleName() + result = this.(Import).getAnImportedModuleName() or result = this.(ImportStar).getImportedModuleName() } - } diff --git a/python/ql/src/semmle/python/Keywords.qll b/python/ql/src/semmle/python/Keywords.qll index 62fe40f95f7..7d8b687f83c 100644 --- a/python/ql/src/semmle/python/Keywords.qll +++ b/python/ql/src/semmle/python/Keywords.qll @@ -1,105 +1,60 @@ import python class KeyValuePair extends KeyValuePair_, DictDisplayItem { - /* syntax: Expr : Expr */ + override Location getLocation() { result = KeyValuePair_.super.getLocation() } - override Location getLocation() { - result = KeyValuePair_.super.getLocation() - } - - override string toString() { - result = KeyValuePair_.super.toString() - } + override string toString() { result = KeyValuePair_.super.toString() } /** Gets the value of this dictionary unpacking. */ - override Expr getValue() { - result = KeyValuePair_.super.getValue() - } + override Expr getValue() { result = KeyValuePair_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } + override Scope getScope() { result = this.getValue().getScope() } override AstNode getAChildNode() { result = this.getKey() or result = this.getValue() } - } /** A double-starred expression in a call or dict literal. */ class DictUnpacking extends DictUnpacking_, DictUnpackingOrKeyword, DictDisplayItem { + override Location getLocation() { result = DictUnpacking_.super.getLocation() } - override Location getLocation() { - result = DictUnpacking_.super.getLocation() - } - - override string toString() { - result = DictUnpacking_.super.toString() - } + override string toString() { result = DictUnpacking_.super.toString() } /** Gets the value of this dictionary unpacking. */ - override Expr getValue() { - result = DictUnpacking_.super.getValue() - } + override Expr getValue() { result = DictUnpacking_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } - - override AstNode getAChildNode() { - result = this.getValue() - } + override Scope getScope() { result = this.getValue().getScope() } + override AstNode getAChildNode() { result = this.getValue() } } abstract class DictUnpackingOrKeyword extends DictItem { - abstract Expr getValue(); - override string toString() { - result = "DictUnpackingOrKeyword with missing toString" - } - + override string toString() { result = "DictUnpackingOrKeyword with missing toString" } } abstract class DictDisplayItem extends DictItem { - abstract Expr getValue(); - override string toString() { - result = "DictDisplayItem with missing toString" - } - + override string toString() { result = "DictDisplayItem with missing toString" } } /** A keyword argument in a call. For example `arg=expr` in `foo(0, arg=expr)` */ -class Keyword extends Keyword_, DictUnpackingOrKeyword { - +class Keyword extends Keyword_, DictUnpackingOrKeyword { /* syntax: name = Expr */ + override Location getLocation() { result = Keyword_.super.getLocation() } - override Location getLocation() { - result = Keyword_.super.getLocation() - } - - override string toString() { - result = Keyword_.super.toString() - } + override string toString() { result = Keyword_.super.toString() } /** Gets the value of this keyword argument. */ - override Expr getValue() { - result = Keyword_.super.getValue() - } + override Expr getValue() { result = Keyword_.super.getValue() } - override Scope getScope() { - result = this.getValue().getScope() - } - - override AstNode getAChildNode() { - result = this.getValue() - } + override Scope getScope() { result = this.getValue().getScope() } + override AstNode getAChildNode() { result = this.getValue() } } - diff --git a/python/ql/src/semmle/python/Metrics.qll b/python/ql/src/semmle/python/Metrics.qll index 66d3179ef4e..694843600bd 100644 --- a/python/ql/src/semmle/python/Metrics.qll +++ b/python/ql/src/semmle/python/Metrics.qll @@ -2,29 +2,23 @@ import python /** The metrics for a function */ class FunctionMetrics extends Function { - - /** Gets the total number of lines (including blank lines) - * from the definition to the end of the function */ - int getNumberOfLines() { - py_alllines(this, result) - } + /** + * Gets the total number of lines (including blank lines) + * from the definition to the end of the function + */ + int getNumberOfLines() { py_alllines(this, result) } /** Gets the number of lines of code in the function */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the function */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstring in the function */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } - /** Cyclomatic complexity: + /** + * Cyclomatic complexity: * The number of linearly independent paths through the source code. * Computed as E - N + 2P, * where @@ -34,14 +28,17 @@ class FunctionMetrics extends Function { */ int getCyclomaticComplexity() { exists(int E, int N | - N = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) - and - E = count(BasicBlock b1, BasicBlock b2 | - b1 = this.getABasicBlock() and b1.likelyReachable() and - b2 = this.getABasicBlock() and b2.likelyReachable() and - b2 = b1.getASuccessor() and not b1.unlikelySuccessor(b2) - ) - | + N = count(BasicBlock b | b = this.getABasicBlock() and b.likelyReachable()) and + E = + count(BasicBlock b1, BasicBlock b2 | + b1 = this.getABasicBlock() and + b1.likelyReachable() and + b2 = this.getABasicBlock() and + b2.likelyReachable() and + b2 = b1.getASuccessor() and + not b1.unlikelySuccessor(b2) + ) + | result = E - N + 2 ) } @@ -51,24 +48,23 @@ class FunctionMetrics extends Function { or exists(BasicBlock mid | mid = this.getABasicBlock() and result = mid.getASuccessor()) } - - /** Dependency of Callables + + /** + * Dependency of Callables * One callable "this" depends on another callable "result" * if "this" makes some call to a method that may end up being "result". - */ + */ FunctionMetrics getADependency() { result != this and not non_coupling_method(result) and - exists(Call call | - call.getScope() = this | - exists(FunctionObject callee | - callee.getFunction() = result | + exists(Call call | call.getScope() = this | + exists(FunctionObject callee | callee.getFunction() = result | call.getAFlowNode().getFunction().refersTo(callee) ) or - exists(Attribute a | - call.getFunc() = a | - unique_root_method(result, a.getName()) or + exists(Attribute a | call.getFunc() = a | + unique_root_method(result, a.getName()) + or exists(Name n | a.getObject() = n and n.getId() = "self" | result.getScope() = this.getScope() and result.getName() = a.getName() @@ -76,145 +72,122 @@ class FunctionMetrics extends Function { ) ) } - - /** Afferent Coupling + + /** + * Afferent Coupling * the number of callables that depend on this method. * This is sometimes called the "fan-in" of a method. */ - int getAfferentCoupling() { - result = count(FunctionMetrics m | m.getADependency() = this ) - } - - /** Efferent Coupling + int getAfferentCoupling() { result = count(FunctionMetrics m | m.getADependency() = this) } + + /** + * Efferent Coupling * the number of methods that this method depends on * This is sometimes called the "fan-out" of a method. */ - int getEfferentCoupling() { - result = count(FunctionMetrics m | this.getADependency() = m) - } + int getEfferentCoupling() { result = count(FunctionMetrics m | this.getADependency() = m) } int getNumberOfParametersWithoutDefault() { - result = this.getPositionalParameterCount() - - count(((FunctionExpr)this.getDefinition()).getArgs().getADefault()) + result = + this.getPositionalParameterCount() - + count(this.getDefinition().(FunctionExpr).getArgs().getADefault()) } - - int getStatementNestingDepth() { - result = max(Stmt s | s.getScope() = this | getNestingDepth(s)) - } - - int getNumberOfCalls() { - result = count(Call c | c.getScope() = this) - } - + + int getStatementNestingDepth() { result = max(Stmt s | s.getScope() = this | getNestingDepth(s)) } + + int getNumberOfCalls() { result = count(Call c | c.getScope() = this) } } /** The metrics for a class */ class ClassMetrics extends Class { - - /** Gets the total number of lines (including blank lines) - * from the definition to the end of the class */ - int getNumberOfLines() { - py_alllines(this, result) - } + /** + * Gets the total number of lines (including blank lines) + * from the definition to the end of the class + */ + int getNumberOfLines() { py_alllines(this, result) } /** Gets the number of lines of code in the class */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the class */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstrings in the class */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } - + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } + private predicate dependsOn(Class other) { other != this and ( - exists(FunctionMetrics f1, FunctionMetrics f2 | - f1.getADependency() = f2 | + exists(FunctionMetrics f1, FunctionMetrics f2 | f1.getADependency() = f2 | f1.getScope() = this and f2.getScope() = other ) or - exists(Function f, Call c, ClassObject cls | - c.getScope() = f and f.getScope() = this | + exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | c.getFunc().refersTo(cls) and cls.getPyClass() = other ) ) } - - /** The afferent coupling of a class is the number of classes that - * directly depend on it. + + /** + * The afferent coupling of a class is the number of classes that + * directly depend on it. */ - int getAfferentCoupling() { - result = count(ClassMetrics t | t.dependsOn(this)) - } - - /** The efferent coupling of a class is the number of classes that + int getAfferentCoupling() { result = count(ClassMetrics t | t.dependsOn(this)) } + + /** + * The efferent coupling of a class is the number of classes that * it directly depends on. */ - int getEfferentCoupling() { - result = count(ClassMetrics t | this.dependsOn(t)) - } - + int getEfferentCoupling() { result = count(ClassMetrics t | this.dependsOn(t)) } + int getInheritanceDepth() { - exists(ClassObject cls | - cls.getPyClass() = this | - result = max(classInheritanceDepth(cls)) - ) + exists(ClassObject cls | cls.getPyClass() = this | result = max(classInheritanceDepth(cls))) } /* -------- CHIDAMBER AND KEMERER LACK OF COHESION IN METHODS ------------ */ - - /* The aim of this metric is to try and determine whether a class - * represents one abstraction (good) or multiple abstractions (bad). - * If a class represents multiple abstractions, it should be split - * up into multiple classes. - * - * In the Chidamber and Kemerer method, this is measured as follows: - * n1 = number of pairs of distinct methods in a class that do *not* - * have at least one commonly accessed field - * n2 = number of pairs of distinct methods in a class that do - * have at least one commonly accessed field - * lcom = ((n1 - n2)/2 max 0) - * + /* + * The aim of this metric is to try and determine whether a class + * represents one abstraction (good) or multiple abstractions (bad). + * If a class represents multiple abstractions, it should be split + * up into multiple classes. + * + * In the Chidamber and Kemerer method, this is measured as follows: + * n1 = number of pairs of distinct methods in a class that do *not* + * have at least one commonly accessed field + * n2 = number of pairs of distinct methods in a class that do + * have at least one commonly accessed field + * lcom = ((n1 - n2)/2 max 0) + * * We divide by 2 because each pair (m1,m2) is counted twice in n1 and n2. */ - + /** should function f be excluded from the cohesion computation? */ - predicate ignoreLackOfCohesion(Function f) { - f.isInitMethod() or f.isSpecialMethod() - } - + predicate ignoreLackOfCohesion(Function f) { f.isInitMethod() or f.isSpecialMethod() } + private predicate methodPair(Function m1, Function m2) { m1.getScope() = this and m2.getScope() = this and - not this.ignoreLackOfCohesion(m1) and + not this.ignoreLackOfCohesion(m1) and not this.ignoreLackOfCohesion(m2) and m1 != m2 } - + private predicate one_accesses_other(Function m1, Function m2) { this.methodPair(m1, m2) and ( - exists(SelfAttributeRead sa | - sa.getName() = m1.getName() and - sa.getScope() = m2 - ) - or - exists(SelfAttributeRead sa | - sa.getName() = m2.getName() and - sa.getScope() = m1 - ) + exists(SelfAttributeRead sa | + sa.getName() = m1.getName() and + sa.getScope() = m2 + ) + or + exists(SelfAttributeRead sa | + sa.getName() = m2.getName() and + sa.getScope() = m1 + ) ) } - - + /** do m1 and m2 access a common field or one calls the other? */ private predicate shareField(Function m1, Function m2) { this.methodPair(m1, m2) and @@ -222,142 +195,117 @@ class ClassMetrics extends Class { exists(SelfAttributeRead sa | sa.getName() = name and sa.getScope() = m1 - ) - and + ) and exists(SelfAttributeRead sa | sa.getName() = name and sa.getScope() = m2 ) ) } - + private int similarMethodPairs() { - result = count(Function m1, Function m2 | - this.methodPair(m1, m2) and - (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) - ) / 2 + result = + count(Function m1, Function m2 | + this.methodPair(m1, m2) and + (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) + ) / 2 } - + private int methodPairs() { - result = count(Function m1, Function m2 | this.methodPair(m1, m2)) / 2 + result = count(Function m1, Function m2 | this.methodPair(m1, m2)) / 2 } - + /** return Chidamber and Kemerer Lack of Cohesion */ int getLackOfCohesionCK() { exists(int n | - n = this.methodPairs() - 2 * this.similarMethodPairs() - and + n = this.methodPairs() - 2 * this.similarMethodPairs() and result = n.maximum(0) - ) - } - - private predicate similarMethodPairDag(Function m1, Function m2, int line) { - (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) and - line = m1.getLocation().getStartLine() and - line < m2.getLocation().getStartLine() - } - - private predicate subgraph(Function m, int line) { - this.similarMethodPairDag(m, _, line) and not this.similarMethodPairDag(_, m, _) - or - exists(Function other | this.subgraph(other, line) | - this.similarMethodPairDag(other, m, _) or - this.similarMethodPairDag(m, other, _) - ) - } - - predicate unionSubgraph(Function m, int line) { - line = min(int l | this.subgraph(m, l)) - } + ) + } - /** return Hitz and Montazeri Lack of Cohesion */ - int getLackOfCohesionHM() { - result = count(int line | - this.unionSubgraph(_, line) - ) - } - + private predicate similarMethodPairDag(Function m1, Function m2, int line) { + (this.shareField(m1, m2) or this.one_accesses_other(m1, m2)) and + line = m1.getLocation().getStartLine() and + line < m2.getLocation().getStartLine() + } + + private predicate subgraph(Function m, int line) { + this.similarMethodPairDag(m, _, line) and not this.similarMethodPairDag(_, m, _) + or + exists(Function other | this.subgraph(other, line) | + this.similarMethodPairDag(other, m, _) or + this.similarMethodPairDag(m, other, _) + ) + } + + predicate unionSubgraph(Function m, int line) { line = min(int l | this.subgraph(m, l)) } + + /** return Hitz and Montazeri Lack of Cohesion */ + int getLackOfCohesionHM() { result = count(int line | this.unionSubgraph(_, line)) } } private int classInheritanceDepth(ClassObject cls) { /* Prevent run-away recursion in case of circular inheritance */ - not cls.getASuperType() = cls - and + not cls.getASuperType() = cls and ( - exists(ClassObject sup | - cls.getABaseType() = sup | - result = classInheritanceDepth(sup) + 1 - ) - or - not exists(cls.getABaseType()) and ( - major_version() = 2 and result = 0 - or - major_version() > 2 and result = 1 - ) + exists(ClassObject sup | cls.getABaseType() = sup | result = classInheritanceDepth(sup) + 1) + or + not exists(cls.getABaseType()) and + ( + major_version() = 2 and result = 0 + or + major_version() > 2 and result = 1 + ) ) } class ModuleMetrics extends Module { - /** Gets the total number of lines (including blank lines) in the module */ - int getNumberOfLines() { - py_alllines(this, result) - } + int getNumberOfLines() { py_alllines(this, result) } - /** Gets the number of lines of code in the module */ - int getNumberOfLinesOfCode() { - py_codelines(this, result) - } + /** Gets the number of lines of code in the module */ + int getNumberOfLinesOfCode() { py_codelines(this, result) } /** Gets the number of lines of comments in the module */ - int getNumberOfLinesOfComments() { - py_commentlines(this, result) - } + int getNumberOfLinesOfComments() { py_commentlines(this, result) } /** Gets the number of lines of docstrings in the module */ - int getNumberOfLinesOfDocStrings() { - py_docstringlines(this, result) - } - - /** The afferent coupling of a class is the number of classes that - * directly depend on it. - */ - int getAfferentCoupling() { - result = count(ModuleMetrics t | t.dependsOn(this)) - } + int getNumberOfLinesOfDocStrings() { py_docstringlines(this, result) } - /** The efferent coupling of a class is the number of classes that + /** + * The afferent coupling of a class is the number of classes that + * directly depend on it. + */ + int getAfferentCoupling() { result = count(ModuleMetrics t | t.dependsOn(this)) } + + /** + * The efferent coupling of a class is the number of classes that * it directly depends on. */ - int getEfferentCoupling() { - result = count(ModuleMetrics t | this.dependsOn(t)) - } + int getEfferentCoupling() { result = count(ModuleMetrics t | this.dependsOn(t)) } private predicate dependsOn(Module other) { other != this and ( - exists(FunctionMetrics f1, FunctionMetrics f2 | - f1.getADependency() = f2 | + exists(FunctionMetrics f1, FunctionMetrics f2 | f1.getADependency() = f2 | f1.getEnclosingModule() = this and f2.getEnclosingModule() = other ) or - exists(Function f, Call c, ClassObject cls | - c.getScope() = f and f.getScope() = this | + exists(Function f, Call c, ClassObject cls | c.getScope() = f and f.getScope() = this | c.getFunc().refersTo(cls) and cls.getPyClass().getEnclosingModule() = other ) ) } - } /** Helpers for coupling */ - predicate unique_root_method(Function func, string name) { - name = func.getName() and - not exists(FunctionObject f, FunctionObject other | + name = func.getName() and + not exists(FunctionObject f, FunctionObject other | f.getFunction() = func and - other.getName() = name | + other.getName() = name + | not other.overrides(f) ) } @@ -375,13 +323,11 @@ predicate non_coupling_method(Function f) { private int getNestingDepth(Stmt s) { not exists(Stmt outer | outer.getASubStatement() = s) and result = 1 or - exists(Stmt outer | - outer.getASubStatement() = s | - if s.(If).isElif() or s instanceof ExceptStmt then + exists(Stmt outer | outer.getASubStatement() = s | + if s.(If).isElif() or s instanceof ExceptStmt + then /* If statement is an `elif` or `except` then it is not indented relative to its parent */ result = getNestingDepth(outer) - else - result = getNestingDepth(outer) + 1 + else result = getNestingDepth(outer) + 1 ) } - diff --git a/python/ql/src/semmle/python/Module.qll b/python/ql/src/semmle/python/Module.qll index 68361d1b12c..4d428636893 100644 --- a/python/ql/src/semmle/python/Module.qll +++ b/python/ql/src/semmle/python/Module.qll @@ -2,47 +2,42 @@ import python private import semmle.python.objects.ObjectAPI private import semmle.python.objects.Modules -/** A module. This is the top level element in an AST, corresponding to a source file. - * It is also a Scope; the scope of global variables. */ +/** + * A module. This is the top level element in an AST, corresponding to a source file. + * It is also a Scope; the scope of global variables. + */ class Module extends Module_, Scope, AstNode { - override string toString() { result = this.getKind() + " " + this.getName() or /* No name is defined, which means that this module is not on an import path. So it must be a script */ - not exists(this.getName()) and not this.isPackage() and + not exists(this.getName()) and + not this.isPackage() and result = "Script " + this.getFile().getShortName() or /* Package missing name, so just use the path instead */ - not exists(this.getName()) and this.isPackage() and - result = "Package at " + this.getPath().getAbsolutePath() + not exists(this.getName()) and + this.isPackage() and + result = "Package at " + this.getPath().getAbsolutePath() } - /** This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. - * The enclosing scope of this module (always none) */ - override Scope getScope() { - none() - } + /** + * This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. + * The enclosing scope of this module (always none) + */ + override Scope getScope() { none() } /** The enclosing scope of this module (always none) */ - override Scope getEnclosingScope() { - none() - } + override Scope getEnclosingScope() { none() } /** Gets the statements forming the body of this module */ - override StmtList getBody() { - result = Module_.super.getBody() - } + override StmtList getBody() { result = Module_.super.getBody() } /** Gets the nth statement of this module */ - override Stmt getStmt(int n) { - result = Module_.super.getStmt(n) - } + override Stmt getStmt(int n) { result = Module_.super.getStmt(n) } /** Gets a top-level statement in this module */ - override Stmt getAStmt() { - result = Module_.super.getAStmt() - } + override Stmt getAStmt() { result = Module_.super.getAStmt() } /** Gets the name of this module */ override string getName() { @@ -54,15 +49,13 @@ class Module extends Module_, Scope, AstNode { /** Gets the short name of the module. For example the short name of module x.y.z is 'z' */ string getShortName() { - result = this.getName().suffix(this.getPackage().getName().length()+1) + result = this.getName().suffix(this.getPackage().getName().length() + 1) or result = this.getName() and not exists(this.getPackage()) } /** Gets this module */ - override Module getEnclosingModule() { - result = this - } + override Module getEnclosingModule() { result = this } /** Gets the __init__ module of this module if the module is a package and it has an __init__ module */ Module getInitModule() { @@ -70,34 +63,25 @@ class Module extends Module_, Scope, AstNode { } /** Whether this module is a package initializer */ - predicate isPackageInit() { - this.getName().matches("%\\_\\_init\\_\\_") and not this.isPackage() - } + predicate isPackageInit() { this.getName().matches("%\\_\\_init\\_\\_") and not this.isPackage() } - /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ + /** Gets a name exported by this module, that is the names that will be added to a namespace by 'from this-module import *' */ string getAnExport() { py_exports(this, result) or - exists(ModuleObjectInternal mod | - mod.getSource() = this.getEntryNode() | + exists(ModuleObjectInternal mod | mod.getSource() = this.getEntryNode() | mod.(ModuleValue).exports(result) ) } /** Gets the source file for this module */ - File getFile() { - py_module_path(this, result) - } + File getFile() { py_module_path(this, result) } /** Gets the source file or folder for this module or package */ - Container getPath() { - py_module_path(this, result) - } + Container getPath() { py_module_path(this, result) } /** Whether this is a package */ - predicate isPackage() { - this.getPath() instanceof Folder - } + predicate isPackage() { this.getPath() instanceof Folder } /** Gets the package containing this module (or parent package if this is a package) */ Module getPackage() { @@ -112,15 +96,13 @@ class Module extends Module_, Scope, AstNode { } /** Gets the metrics for this module */ - ModuleMetrics getMetrics() { - result = this - } + ModuleMetrics getMetrics() { result = this } - /** Use ModuleObject.getAnImportedModule() instead. - * Gets a module imported by this module */ - deprecated Module getAnImportedModule() { - result.getName() = this.getAnImportedModuleName() - } + /** + * Use ModuleObject.getAnImportedModule() instead. + * Gets a module imported by this module + */ + deprecated Module getAnImportedModule() { result.getName() = this.getAnImportedModuleName() } string getAnImportedModuleName() { exists(Import i | i.getEnclosingModule() = this | result = i.getAnImportedModuleName()) @@ -142,22 +124,23 @@ class Module extends Module_, Scope, AstNode { } /** Whether name is declared in the __all__ list of this module */ - predicate declaredInAll(string name) - { + predicate declaredInAll(string name) { exists(AssignStmt a, GlobalVariable all | - a.defines(all) and a.getScope() = this and - all.getId() = "__all__" and ((List)a.getValue()).getAnElt().(StrConst).getText() = name + a.defines(all) and + a.getScope() = this and + all.getId() = "__all__" and + a.getValue().(List).getAnElt().(StrConst).getText() = name ) } - override AstNode getAChildNode() { - result = this.getAStmt() - } + override AstNode getAChildNode() { result = this.getAStmt() } predicate hasFromFuture(string attr) { exists(Import i, ImportMember im, ImportExpr ie, Alias a, Name name | - im.getModule() = ie and ie.getName() = "__future__" and - a.getAsname() = name and name.getId() = attr and + im.getModule() = ie and + ie.getName() = "__future__" and + a.getAsname() = name and + name.getId() = attr and i.getASubExpression() = im and i.getAName() = a and i.getEnclosingModule() = this @@ -165,55 +148,40 @@ class Module extends Module_, Scope, AstNode { } /** Gets the path element from which this module was loaded. */ - Container getLoadPath() { - result = this.getPath().getImportRoot() - } + Container getLoadPath() { result = this.getPath().getImportRoot() } /** Holds if this module is in the standard library for version `major.minor` */ - predicate inStdLib(int major, int minor) { - this.getLoadPath().isStdLibRoot(major, minor) - } + predicate inStdLib(int major, int minor) { this.getLoadPath().isStdLibRoot(major, minor) } /** Holds if this module is in the standard library */ - predicate inStdLib() { - this.getLoadPath().isStdLibRoot() - } + predicate inStdLib() { this.getLoadPath().isStdLibRoot() } - override - predicate containsInScope(AstNode inner) { - Scope.super.containsInScope(inner) - } + override predicate containsInScope(AstNode inner) { Scope.super.containsInScope(inner) } - override - predicate contains(AstNode inner) { - Scope.super.contains(inner) - } + override predicate contains(AstNode inner) { Scope.super.contains(inner) } /** Gets the kind of this module. */ override string getKind() { - if this.isPackage() then - result = "Package" + if this.isPackage() + then result = "Package" else ( not exists(Module_.super.getKind()) and result = "Module" or result = Module_.super.getKind() ) } - } - bindingset[name] private predicate legalDottedName(string name) { name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*(\\.(\\p{L}|_)(\\p{L}|\\d|_)*)*") } bindingset[name] -private predicate legalShortName(string name) { - name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*") -} +private predicate legalShortName(string name) { name.regexpMatch("(\\p{L}|_)(\\p{L}|\\d|_)*") } -/** Holds if `f` is potentially a source package. +/** + * Holds if `f` is potentially a source package. * Does it have an __init__.py file (or --respect-init=False for Python 2) and is it within the source archive? */ private predicate isPotentialSourcePackage(Folder f) { @@ -240,8 +208,12 @@ string moduleNameFromFile(Container file) { result = moduleNameFromFile(file.getParent()) + "." + basename ) or - isPotentialSourcePackage(file) and result = file.getStem() and - (not isPotentialSourcePackage(file.getParent()) or not legalShortName(file.getParent().getBaseName())) + isPotentialSourcePackage(file) and + result = file.getStem() and + ( + not isPotentialSourcePackage(file.getParent()) or + not legalShortName(file.getParent().getBaseName()) + ) or result = file.getStem() and file.getParent() = file.getImportRoot() or @@ -253,8 +225,8 @@ private predicate isStubRoot(Folder f) { f.getAbsolutePath().matches("%/data/python/stubs") } - -/** Holds if the Container `c` should be the preferred file or folder for +/** + * Holds if the Container `c` should be the preferred file or folder for * the given name when performing imports. * Trivially true for any container if it is the only one with its name. * However, if there are several modules with the same name, then diff --git a/python/ql/src/semmle/python/Operations.qll b/python/ql/src/semmle/python/Operations.qll index 5931a88fce5..c6dd102350c 100644 --- a/python/ql/src/semmle/python/Operations.qll +++ b/python/ql/src/semmle/python/Operations.qll @@ -2,123 +2,86 @@ import python /** Base class for operators */ class Operator extends Operator_ { - /** Gets the name of the special method used to implement this operator */ string getSpecialMethodName() { none() } - } /* Unary Expression and its operators */ - /** A unary expression: (`+x`), (`-x`) or (`~x`) */ class UnaryExpr extends UnaryExpr_ { - - override Expr getASubExpression() { - result = this.getOperand() - } - + override Expr getASubExpression() { result = this.getOperand() } } /** A unary operator: `+`, `-`, `~` or `not` */ class Unaryop extends Unaryop_ { - /** Gets the name of the special method used to implement this operator */ string getSpecialMethodName() { none() } - } /** An invert (`~`) unary operator */ class Invert extends Invert_ { - override string getSpecialMethodName() { result = "__invert__" } - } -/** A positive (`+`) unary operator */ +/** A positive (`+`) unary operator */ class UAdd extends UAdd_ { - override string getSpecialMethodName() { result = "__pos__" } - } /** A negation (`-`) unary operator */ class USub extends USub_ { - override string getSpecialMethodName() { result = "__neg__" } - } /** A `not` unary operator */ class Not extends Not_ { - override string getSpecialMethodName() { none() } - } - /* Binary Operation and its operators */ - /** A binary expression, such as `x + y` */ class BinaryExpr extends BinaryExpr_ { - - override Expr getASubExpression() { - result = this.getLeft() or result = this.getRight() - } - + override Expr getASubExpression() { result = this.getLeft() or result = this.getRight() } } /** A power (`**`) binary operator */ class Pow extends Pow_ { - override string getSpecialMethodName() { result = "__pow__" } - } /** A right shift (`>>`) binary operator */ class RShift extends RShift_ { - override string getSpecialMethodName() { result = "__rshift__" } - } /** A subtract (`-`) binary operator */ class Sub extends Sub_ { - override string getSpecialMethodName() { result = "__sub__" } - } /** A bitwise and (`&`) binary operator */ class BitAnd extends BitAnd_ { - override string getSpecialMethodName() { result = "__and__" } - } /** A bitwise or (`|`) binary operator */ class BitOr extends BitOr_ { - override string getSpecialMethodName() { result = "__or__" } - } /** A bitwise exclusive-or (`^`) binary operator */ class BitXor extends BitXor_ { - override string getSpecialMethodName() { result = "__xor__" } - } /** An add (`+`) binary operator */ class Add extends Add_ { - override string getSpecialMethodName() { result = "__add__" } } /** An (true) divide (`/`) binary operator */ class Div extends Div_ { - - override string getSpecialMethodName() { + override string getSpecialMethodName() { result = "__truediv__" or major_version() = 2 and result = "__div__" @@ -127,185 +90,123 @@ class Div extends Div_ { /** An floor divide (`//`) binary operator */ class FloorDiv extends FloorDiv_ { - override string getSpecialMethodName() { result = "__floordiv__" } - } /** A left shift (`<<`) binary operator */ class LShift extends LShift_ { - override string getSpecialMethodName() { result = "__lshift__" } - } /** A modulo (`%`) binary operator, which includes string formatting */ class Mod extends Mod_ { - override string getSpecialMethodName() { result = "__mod__" } - } /** A multiplication (`*`) binary operator */ class Mult extends Mult_ { - override string getSpecialMethodName() { result = "__mul__" } - } /** A matrix multiplication (`@`) binary operator */ class MatMult extends MatMult_ { - override string getSpecialMethodName() { result = "__matmul__" } - } /* Comparison Operation and its operators */ - /** A comparison operation, such as `x`) comparison operator */ class Gt extends Gt_ { - - override string getSymbol() { - result = ">" - } + override string getSymbol() { result = ">" } override string getSpecialMethodName() { result = "__gt__" } - } /** A greater than or equals (`>=`) comparison operator */ class GtE extends GtE_ { - - override string getSymbol() { - result = ">=" - } + override string getSymbol() { result = ">=" } override string getSpecialMethodName() { result = "__ge__" } - } /** An `in` comparison operator */ class In extends In_ { - - override string getSymbol() { - result = "in" - } - + override string getSymbol() { result = "in" } } /** An `is` comparison operator */ class Is extends Is_ { - - override string getSymbol() { - result = "is" - } - + override string getSymbol() { result = "is" } } /** An `is not` comparison operator */ class IsNot extends IsNot_ { - - override string getSymbol() { - result = "is not" - } - + override string getSymbol() { result = "is not" } } /** An equals (`==`) comparison operator */ class Eq extends Eq_ { - - override string getSymbol() { - result = "==" - } + override string getSymbol() { result = "==" } override string getSpecialMethodName() { result = "__eq__" } - } /** A less than (`<`) comparison operator */ class Lt extends Lt_ { - - override string getSymbol() { - result = "<" - } + override string getSymbol() { result = "<" } override string getSpecialMethodName() { result = "__lt__" } - } /** A less than or equals (`<=`) comparison operator */ class LtE extends LtE_ { - - override string getSymbol() { - result = "<=" - } + override string getSymbol() { result = "<=" } override string getSpecialMethodName() { result = "__le__" } - } /** A not equals (`!=`) comparison operator */ class NotEq extends NotEq_ { - - override string getSymbol() { - result = "!=" - } + override string getSymbol() { result = "!=" } override string getSpecialMethodName() { result = "__ne__" } - } /** An `not in` comparison operator */ class NotIn extends NotIn_ { - - override string getSymbol() { - result = "not in" - } - + override string getSymbol() { result = "not in" } } /* Boolean Operation (and/or) and its operators */ - /** A boolean shortcut (and/or) operation */ class BoolExpr extends BoolExpr_ { - - override Expr getASubExpression() { - result = this.getAValue() - } + override Expr getASubExpression() { result = this.getAValue() } string getOperator() { this.getOp() instanceof And and result = "and" @@ -315,30 +216,24 @@ class BoolExpr extends BoolExpr_ { /** Whether part evaluates to partIsTrue if this evaluates to wholeIsTrue */ predicate impliesValue(Expr part, boolean partIsTrue, boolean wholeIsTrue) { - if this.getOp() instanceof And then ( + if this.getOp() instanceof And + then ( wholeIsTrue = true and partIsTrue = true and part = this.getAValue() or - wholeIsTrue = true and ((BoolExpr)this.getAValue()).impliesValue(part, partIsTrue, true) + wholeIsTrue = true and this.getAValue().(BoolExpr).impliesValue(part, partIsTrue, true) ) else ( wholeIsTrue = false and partIsTrue = false and part = this.getAValue() or - wholeIsTrue = false and ((BoolExpr)this.getAValue()).impliesValue(part, partIsTrue, false) + wholeIsTrue = false and this.getAValue().(BoolExpr).impliesValue(part, partIsTrue, false) ) } - } /** A short circuit boolean operator, and/or */ -class Boolop extends Boolop_ { - -} +class Boolop extends Boolop_ { } /** An `and` boolean operator */ -class And extends And_ { - -} +class And extends And_ { } /** An `or` boolean operator */ -class Or extends Or_ { - -} +class Or extends Or_ { } diff --git a/python/ql/src/semmle/python/SSA.qll b/python/ql/src/semmle/python/SSA.qll index 3035166824a..68a6b1db803 100644 --- a/python/ql/src/semmle/python/SSA.qll +++ b/python/ql/src/semmle/python/SSA.qll @@ -2,40 +2,33 @@ import python -/** A single static assignment variable. +/** + * A single static assignment variable. * An SSA variable is a variable which is only assigned once (statically). * SSA variables can be defined as normal variables or by a phi node which can occur at joins in the flow graph. * Definitions without uses do not have a SSA variable. */ -class SsaVariable extends @py_ssa_var{ - - SsaVariable() { - py_ssa_var(this, _) - } +class SsaVariable extends @py_ssa_var { + SsaVariable() { py_ssa_var(this, _) } /** Gets the source variable */ - Variable getVariable() { - py_ssa_var(this, result) - } + Variable getVariable() { py_ssa_var(this, result) } /** Gets a use of this variable */ - ControlFlowNode getAUse() { - py_ssa_use(result, this) - } + ControlFlowNode getAUse() { py_ssa_use(result, this) } /** Gets the definition (which may be a deletion) of this SSA variable */ - ControlFlowNode getDefinition() { - py_ssa_defn(this, result) - } + ControlFlowNode getDefinition() { py_ssa_defn(this, result) } - /** Gets an argument of the phi function defining this variable. + /** + * Gets an argument of the phi function defining this variable. * This predicate uses the raw SSA form produced by the extractor. - * In general, you should use `getAPrunedPhiInput()` instead. */ - SsaVariable getAPhiInput() { - py_ssa_phi(this, result) - } + * In general, you should use `getAPrunedPhiInput()` instead. + */ + SsaVariable getAPhiInput() { py_ssa_phi(this, result) } - /** Gets the edge(s) (result->this.getDefinition()) on which the SSA variable 'input' defines this SSA variable. + /** + * Gets the edge(s) (result->this.getDefinition()) on which the SSA variable 'input' defines this SSA variable. * For each incoming edge `X->B`, where `B` is the basic block containing this phi-node, only one of the input SSA variables * for this phi-node is live. This predicate returns the predecessor block such that the variable 'input' * is the live variable on the edge result->B. @@ -44,23 +37,25 @@ class SsaVariable extends @py_ssa_var{ input = this.getAPhiInput() and result = this.getAPredecessorBlockForPhi() and input.getDefinition().getBasicBlock().dominates(result) and - /* Beware the case where an SSA variable that is an input on one edge dominates another edge. + /* + * Beware the case where an SSA variable that is an input on one edge dominates another edge. * Consider (in SSA form): * x0 = 0 * if cond: * x1 = 1 * x2 = phi(x0, x1) * use(x2) - * + * * The definition of x0 dominates the exit from the block x1=1, even though it does not reach it. * Hence we need to check that no other definition dominates the edge and actually reaches it. * Note that if a dominates c and b dominates c, then either a dominates b or vice-versa. */ + not exists(SsaVariable other, BasicBlock other_def | not other = input and other = this.getAPhiInput() and other_def = other.getDefinition().getBasicBlock() - | + | other_def.dominates(result) and input.getDefinition().getBasicBlock().strictlyDominates(other_def) ) @@ -81,22 +76,16 @@ class SsaVariable extends @py_ssa_var{ result = this.getAPhiInput().getAnUltimateDefinition() } - string toString() { - result = "SSA Variable " + this.getId() - } + string toString() { result = "SSA Variable " + this.getId() } - Location getLocation() { - result = this.getDefinition().getLocation() - } + Location getLocation() { result = this.getDefinition().getLocation() } /** Gets the id (name) of this variable */ - string getId() { - result = this.getVariable().getId() - } + string getId() { result = this.getVariable().getId() } /** Gets the incoming edges for a Phi node. */ private BasicBlock getAPredecessorBlockForPhi() { - exists(getAPhiInput()) and + exists(getAPhiInput()) and result.getASuccessor() = this.getDefinition().getBasicBlock() } @@ -112,11 +101,13 @@ class SsaVariable extends @py_ssa_var{ or exists(SsaVariable var | var = this.getAPhiInput() | var.reachableWithoutDefinition()) or - /* For phi-nodes, there must be a corresponding phi-input for each control-flow + /* + * For phi-nodes, there must be a corresponding phi-input for each control-flow * predecessor. Otherwise, the variable will be undefined on that incoming edge. * WARNING: the same phi-input may cover multiple predecessors, so this check * cannot be done by counting. */ + exists(BasicBlock incoming | incoming = this.getAPredecessorBlockForPhi() and not this.getAPhiInput().getDefinition().getBasicBlock().dominates(incoming) @@ -131,11 +122,13 @@ class SsaVariable extends @py_ssa_var{ or exists(SsaVariable var | var = this.getAPrunedPhiInput() | var.maybeUndefined()) or - /* For phi-nodes, there must be a corresponding phi-input for each control-flow + /* + * For phi-nodes, there must be a corresponding phi-input for each control-flow * predecessor. Otherwise, the variable will be undefined on that incoming edge. * WARNING: the same phi-input may cover multiple predecessors, so this check * cannot be done by counting. */ + exists(BasicBlock incoming | reaches_end(incoming) and incoming = this.getAPrunedPredecessorBlockForPhi() and @@ -144,14 +137,17 @@ class SsaVariable extends @py_ssa_var{ } private predicate implicitlyDefined() { - not exists(this.getDefinition()) and not py_ssa_phi(this, _) and + not exists(this.getDefinition()) and + not py_ssa_phi(this, _) and exists(GlobalVariable var | this.getVariable() = var | - globallyDefinedName(var.getId()) or - var.getId() = "__path__" and ((Module)var.getScope()).isPackageInit() + globallyDefinedName(var.getId()) + or + var.getId() = "__path__" and var.getScope().(Module).isPackageInit() ) } - /** Gets the global variable that is accessed if this local is undefined. + /** + * Gets the global variable that is accessed if this local is undefined. * Only applies to local variables in class scopes. */ GlobalVariable getFallbackGlobal() { @@ -163,28 +159,26 @@ class SsaVariable extends @py_ssa_var{ ) } - /* Whether this SSA variable is the first parameter of a method + /* + * Whether this SSA variable is the first parameter of a method * (regardless of whether it is actually called self or not) */ + predicate isSelf() { - exists(Function func | - func.isMethod() - and + exists(Function func | + func.isMethod() and this.getDefinition().getNode() = func.getArg(0) ) } } private predicate reaches_end(BasicBlock b) { - not exits_early(b) - and + not exits_early(b) and ( - /* Entry point */ - not exists(BasicBlock prev | prev.getASuccessor() = b) - or - exists(BasicBlock prev | prev.getASuccessor() = b | - reaches_end(prev) - ) + /* Entry point */ + not exists(BasicBlock prev | prev.getASuccessor() = b) + or + exists(BasicBlock prev | prev.getASuccessor() = b | reaches_end(prev)) ) } @@ -209,32 +203,19 @@ private predicate builtin_constant(string name) { } private predicate auto_name(string name) { - name = "__file__" or name = "__builtins__" or name = "__name__" + name = "__file__" or name = "__builtins__" or name = "__name__" } /** Whether this name is (almost) always defined, ie. it is a builtin or VM defined name */ -predicate globallyDefinedName(string name) { - builtin_constant(name) or auto_name(name) -} +predicate globallyDefinedName(string name) { builtin_constant(name) or auto_name(name) } /** An SSA variable that is backed by a global variable */ class GlobalSsaVariable extends EssaVariable { + GlobalSsaVariable() { this.getSourceVariable() instanceof GlobalVariable } - GlobalSsaVariable() { - this.getSourceVariable() instanceof GlobalVariable - } - - GlobalVariable getVariable() { - result = this.getSourceVariable() - } - - string getId() { - result = this.getVariable().getId() - } - - override string toString() { - result = "GSSA Variable " + this.getId() - } + GlobalVariable getVariable() { result = this.getSourceVariable() } + string getId() { result = this.getVariable().getId() } + override string toString() { result = "GSSA Variable " + this.getId() } } diff --git a/python/ql/src/semmle/python/Scope.qll b/python/ql/src/semmle/python/Scope.qll index 112b3d10cc5..1fab7f77013 100755 --- a/python/ql/src/semmle/python/Scope.qll +++ b/python/ql/src/semmle/python/Scope.qll @@ -1,80 +1,58 @@ import python -/** A Scope. A scope is the lexical extent over which all identifiers with the same name refer to the same variable. +/** + * A Scope. A scope is the lexical extent over which all identifiers with the same name refer to the same variable. * Modules, Classes and Functions are all Scopes. There are no other scopes. - * The scopes for expressions that create new scopes, lambdas and comprehensions, are handled by creating an anonymous Function. */ + * The scopes for expressions that create new scopes, lambdas and comprehensions, are handled by creating an anonymous Function. + */ class Scope extends Scope_ { + Module getEnclosingModule() { result = this.getEnclosingScope().getEnclosingModule() } - Module getEnclosingModule() { - result = this.getEnclosingScope().getEnclosingModule() - } - - /** This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. + /** + * This method will be deprecated in the next release. Please use `getEnclosingScope()` instead. * The reason for this is to avoid confusion around use of `x.getScope+()` where `x` might be an * `AstNode` or a `Variable`. Forcing the users to write `x.getScope().getEnclosingScope*()` ensures that * the apparent semantics and the actual semantics coincide. * [ Gets the scope enclosing this scope (modules have no enclosing scope) ] */ - Scope getScope() { - none() - } + Scope getScope() { none() } /** Gets the scope enclosing this scope (modules have no enclosing scope) */ - Scope getEnclosingScope() { - none() - } + Scope getEnclosingScope() { none() } /** Gets the statements forming the body of this scope */ - StmtList getBody() { - none() - } + StmtList getBody() { none() } /** Gets the nth statement of this scope */ - Stmt getStmt(int n) { - none() - } + Stmt getStmt(int n) { none() } /** Gets a top-level statement in this scope */ - Stmt getAStmt() { - none() - } + Stmt getAStmt() { none() } - Location getLocation() { - none() - } + Location getLocation() { none() } /** Gets the name of this scope */ - string getName() { - py_strs(result, this, 0) - } + string getName() { py_strs(result, this, 0) } /** Gets the docstring for this scope */ - StrConst getDocString() { - result = ((ExprStmt)this.getStmt(0)).getValue() - } + StrConst getDocString() { result = this.getStmt(0).(ExprStmt).getValue() } /** Gets the entry point into this Scope's control flow graph */ - ControlFlowNode getEntryNode() { - py_scope_flow(result, this, -1) - } + ControlFlowNode getEntryNode() { py_scope_flow(result, this, -1) } /** Gets the non-explicit exit from this Scope's control flow graph */ - ControlFlowNode getFallthroughNode() { - py_scope_flow(result, this, 0) - } + ControlFlowNode getFallthroughNode() { py_scope_flow(result, this, 0) } /** Gets the exit of this scope following from a return statement */ - ControlFlowNode getReturnNode() { - py_scope_flow(result, this, 2) - } + ControlFlowNode getReturnNode() { py_scope_flow(result, this, 2) } /** Gets an exit from this Scope's control flow graph */ - ControlFlowNode getAnExitNode() { - exists (int i | py_scope_flow(result, this, i) and i >= 0) - } + ControlFlowNode getAnExitNode() { exists(int i | py_scope_flow(result, this, i) and i >= 0) } - /** Gets an exit from this Scope's control flow graph, - * that does not result from an exception */ + /** + * Gets an exit from this Scope's control flow graph, + * that does not result from an exception + */ ControlFlowNode getANormalExit() { result = this.getFallthroughNode() or @@ -82,9 +60,7 @@ class Scope extends Scope_ { } /** Holds if this a top-level (non-nested) class or function */ - predicate isTopLevel() { - this.getEnclosingModule() = this.getEnclosingScope() - } + predicate isTopLevel() { this.getEnclosingModule() = this.getEnclosingScope() } /** Holds if this scope is deemed to be public */ predicate isPublic() { @@ -93,10 +69,9 @@ class Scope extends Scope_ { /* Not implicitly private */ this.getName().charAt(0) != "_" and ( - this instanceof Module + this instanceof Module or - exists(Module m | - m = this.getEnclosingScope() and m.isPublic() | + exists(Module m | m = this.getEnclosingScope() and m.isPublic() | /* If the module has an __all__, is this in it */ not exists(m.getAnExport()) or @@ -116,66 +91,63 @@ class Scope extends Scope_ { exists(Scope inner | inner.getEnclosingScope() = this | inner.contains(a)) } - /** Holds if this scope can be expected to execute before `other`. + /** + * Holds if this scope can be expected to execute before `other`. * Modules precede functions and methods in those modules * `__init__` precedes other methods. `__enter__` precedes `__exit__`. - * NOTE that this is context-insensitive, so a module "precedes" a function + * NOTE that this is context-insensitive, so a module "precedes" a function * in that module, even if that function is called from the module scope. */ predicate precedes(Scope other) { - exists(Function f, string name | - f = other and name = f.getName() | - if f.isMethod() then ( + exists(Function f, string name | f = other and name = f.getName() | + if f.isMethod() + then // The __init__ method is preceded by the enclosing module this = f.getEnclosingModule() and name = "__init__" or exists(Class c, string pred_name | // __init__ -> __enter__ -> __exit__ // __init__ -> other-methods - f.getScope() = c and ( + f.getScope() = c and + ( pred_name = "__init__" and not name = "__init__" and not name = "__exit__" or pred_name = "__enter__" and name = "__exit__" ) - | + | this.getScope() = c and pred_name = this.(Function).getName() or not exists(Function pre_func | pre_func.getName() = pred_name and pre_func.getScope() = c - ) and this = other.getEnclosingModule() + ) and + this = other.getEnclosingModule() ) - ) else ( + else // Normal functions are preceded by the enclosing module this = f.getEnclosingModule() - ) ) } - /** Gets the evaluation scope for code in this (lexical) scope. + /** + * Gets the evaluation scope for code in this (lexical) scope. * This is usually the scope itself, but may be an enclosing scope. * Notably, for list comprehensions in Python 2. */ - Scope getEvaluatingScope() { - result = this - } + Scope getEvaluatingScope() { result = this } - /** Holds if this scope is in the source archive, + /** + * Holds if this scope is in the source archive, * that is it is part of the code specified, not library code */ - predicate inSource() { - exists(this.getEnclosingModule().getFile().getRelativePath()) - } + predicate inSource() { exists(this.getEnclosingModule().getFile().getRelativePath()) } - Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } + Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } /** Whether this contains `inner` syntactically and `inner` has the same scope as `this` */ predicate containsInScope(AstNode inner) { this.getBody().contains(inner) and this = inner.getScope() } - } diff --git a/python/ql/src/semmle/python/SelfAttribute.qll b/python/ql/src/semmle/python/SelfAttribute.qll index e970aa6c3d9..c40b3b3c0be 100644 --- a/python/ql/src/semmle/python/SelfAttribute.qll +++ b/python/ql/src/semmle/python/SelfAttribute.qll @@ -1,23 +1,19 @@ -/** Utilities to support queries about instance attribute accesses of +/** + * Utilities to support queries about instance attribute accesses of * the form `self.attr`. */ import python private import semmle.python.pointsto.Filters -/** An attribute access where the left hand side of the attribute expression - * is `self`. - */ +/** + * An attribute access where the left hand side of the attribute expression + * is `self`. + */ class SelfAttribute extends Attribute { + SelfAttribute() { self_attribute(this, _) } - SelfAttribute() { - self_attribute(this, _) - } - - Class getClass() { - self_attribute(this, result) - } - + Class getClass() { self_attribute(this, result) } } /** Whether variable 'self' is the self variable in method 'method' */ @@ -29,8 +25,7 @@ private predicate self_variable(Function method, Variable self) { /** Whether attribute is an access of the form `self.attr` in the body of the class 'cls' */ private predicate self_attribute(Attribute attr, Class cls) { - exists(Function f, Variable self | - self_variable(f, self) | + exists(Function f, Variable self | self_variable(f, self) | self.getAnAccess() = attr.getObject() and cls = f.getScope+() ) @@ -38,14 +33,12 @@ private predicate self_attribute(Attribute attr, Class cls) { /** Helper class for UndefinedClassAttribute.ql & MaybeUndefinedClassAttribute.ql */ class SelfAttributeRead extends SelfAttribute { - SelfAttributeRead() { this.getCtx() instanceof Load and - // Be stricter for loads. + // Be stricter for loads. // We want to generous as to what is defined (i.e. stores), // but strict as to what needs to be defined (i.e. loads). - exists(ClassObject cls, FunctionObject func | - cls.declaredAttribute(_) = func | + exists(ClassObject cls, FunctionObject func | cls.declaredAttribute(_) = func | func.getFunction() = this.getScope() and cls.getPyClass() = this.getClass() ) @@ -59,35 +52,28 @@ class SelfAttributeRead extends SelfAttribute { ) } - pragma [noinline] predicate locallyDefined() { + pragma[noinline] + predicate locallyDefined() { exists(SelfAttributeStore store | - this.getName() = store.getName() and - this.getScope() = store.getScope() | + this.getName() = store.getName() and + this.getScope() = store.getScope() + | store.getAFlowNode().strictlyDominates(this.getAFlowNode()) ) } - } class SelfAttributeStore extends SelfAttribute { + SelfAttributeStore() { this.getCtx() instanceof Store } - SelfAttributeStore() { - this.getCtx() instanceof Store - } - - Expr getAssignedValue() { - exists(Assign a | a.getATarget() = this | - result = a.getValue() - ) - } - + Expr getAssignedValue() { exists(Assign a | a.getATarget() = this | result = a.getValue()) } } private predicate attr_assigned_in_method_arg_n(FunctionObject method, string name, int n) { exists(SsaVariable param | method.getFunction().getArg(n).asName() = param.getDefinition().getNode() - | - exists(AttrNode attr | + | + exists(AttrNode attr | attr.getObject(name) = param.getAUse() and attr.isStore() ) diff --git a/python/ql/src/semmle/python/Stmts.qll b/python/ql/src/semmle/python/Stmts.qll index 4d8c45b70a8..cc67747923a 100644 --- a/python/ql/src/semmle/python/Stmts.qll +++ b/python/ql/src/semmle/python/Stmts.qll @@ -2,34 +2,21 @@ import python /** A statement */ class Stmt extends Stmt_, AstNode { - /** Gets the scope immediately enclosing this statement */ - override Scope getScope() { - py_scopes(this, result) - } + override Scope getScope() { py_scopes(this, result) } - override string toString() { - result = "Stmt" - } + override string toString() { result = "Stmt" } /** Gets the module enclosing this statement */ - Module getEnclosingModule() { - result = this.getScope().getEnclosingModule() - } + Module getEnclosingModule() { result = this.getScope().getEnclosingModule() } - override Location getLocation() { - result = Stmt_.super.getLocation() - } + override Location getLocation() { result = Stmt_.super.getLocation() } /** Gets an immediate (non-nested) sub-expression of this statement */ - Expr getASubExpression() { - none() - } + Expr getASubExpression() { none() } /** Gets an immediate (non-nested) sub-statement of this statement */ - Stmt getASubStatement() { - none() - } + Stmt getASubStatement() { none() } override AstNode getAChildNode() { result = this.getASubExpression() @@ -42,8 +29,8 @@ class Stmt extends Stmt_, AstNode { this.containsInScope(result.getNode()) } - - /** Gets a control flow node for an entry into this statement. + /** + * Gets a control flow node for an entry into this statement. */ ControlFlowNode getAnEntryNode() { result = this.possibleEntryNode() and @@ -60,131 +47,94 @@ class Stmt extends Stmt_, AstNode { exists(If ifstmt | ifstmt.getTest().(ImmutableLiteral).booleanValue() = false and ifstmt.getBody().contains(this) or - ifstmt.getTest().(ImmutableLiteral).booleanValue() = true and ifstmt.getOrelse().contains(this) + ifstmt.getTest().(ImmutableLiteral).booleanValue() = true and + ifstmt.getOrelse().contains(this) ) or exists(While whilestmt | - whilestmt.getTest().(ImmutableLiteral).booleanValue() = false and whilestmt.getBody().contains(this) + whilestmt.getTest().(ImmutableLiteral).booleanValue() = false and + whilestmt.getBody().contains(this) ) } - /** Gets the final statement in this statement, ordered by location. + /** + * Gets the final statement in this statement, ordered by location. * Will be this statement if not a compound statement. */ - Stmt getLastStatement() { - result = this - } - + Stmt getLastStatement() { result = this } } /** A statement that includes a binding (except imports) */ class Assign extends Assign_ { - /** Use ControlFlowNodes and SsaVariables for data-flow analysis. */ - predicate defines(Variable v) { - this.getATarget().defines(v) - } + predicate defines(Variable v) { this.getATarget().defines(v) } override Expr getASubExpression() { result = this.getATarget() or result = this.getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An assignment statement */ class AssignStmt extends Assign { - /* syntax: Expr, ... = Expr */ + AssignStmt() { not this instanceof FunctionDef and not this instanceof ClassDef } - AssignStmt() { - not this instanceof FunctionDef and not this instanceof ClassDef - } - - override string toString() { - result = "AssignStmt" - } + override string toString() { result = "AssignStmt" } } /** An augmented assignment statement, such as `x += y` */ class AugAssign extends AugAssign_ { - /* syntax: Expr += Expr */ + override Expr getASubExpression() { result = this.getOperation() } - override Expr getASubExpression() { - result = this.getOperation() - } + Expr getTarget() { result = this.getOperation().(BinaryExpr).getLeft() } - Expr getTarget() { - result = ((BinaryExpr)this.getOperation()).getLeft() - } + Expr getValue() { result = this.getOperation().(BinaryExpr).getRight() } - Expr getValue() { - result = ((BinaryExpr)this.getOperation()).getRight() - } - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An annotated assignment statement, such as `x: int = 0` */ class AnnAssign extends AnnAssign_ { - /* syntax: Expr: Expr = Expr */ - override Expr getASubExpression() { result = this.getAnnotation() or result = this.getTarget() or result = this.getValue() } - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } /** Holds if the value of the annotation of this assignment is stored at runtime. */ predicate isStored() { - not this.getScope() instanceof Function - and + not this.getScope() instanceof Function and exists(Name n | - n = this.getTarget() - and + n = this.getTarget() and not n.isParenthesized() ) } - } /** An exec statement */ class Exec extends Exec_ { - /* syntax: exec Expr */ - override Expr getASubExpression() { result = this.getBody() or result = this.getGlobals() or result = this.getLocals() } - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** An except statement (part of a `try` statement), such as `except IOError as err:` */ class ExceptStmt extends ExceptStmt_ { - /* syntax: except Expr [ as Expr ]: */ - /** Gets the immediately enclosing try statement */ - Try getTry() { - result.getAHandler() = this - } + Try getTry() { result.getAHandler() = this } override Expr getASubExpression() { result = this.getName() @@ -192,96 +142,54 @@ class ExceptStmt extends ExceptStmt_ { result = this.getType() } - override Stmt getASubStatement() { - result = this.getAStmt() - } - - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } + override Stmt getASubStatement() { result = this.getAStmt() } + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** An assert statement, such as `assert a == b, "A is not equal to b"` */ class Assert extends Assert_ { - /* syntax: assert Expr [, Expr] */ + override Expr getASubExpression() { result = this.getMsg() or result = this.getTest() } - override Expr getASubExpression() { - result = this.getMsg() or result = this.getTest() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A break statement */ class Break extends Break_ { - /* syntax: assert Expr [, Expr] */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A continue statement */ class Continue extends Continue_ { - /* syntax: continue */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A delete statement, such as `del x[-1]` */ class Delete extends Delete_ { - /* syntax: del Expr, ... */ + override Expr getASubExpression() { result = this.getATarget() } - override Expr getASubExpression() { - result = this.getATarget() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** An expression statement, such as `len(x)` or `yield y` */ class ExprStmt extends ExprStmt_ { - /* syntax: Expr */ + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } /** A for statement, such as `for x in y: print(x)` */ class For extends For_ { - /* syntax: for varname in Expr: ... */ - override Stmt getASubStatement() { result = this.getAStmt() or result = this.getAnOrelse() @@ -292,39 +200,26 @@ class For extends For_ { result = this.getIter() } - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() - } - + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** A global statement, such as `global var` */ class Global extends Global_ { - /* syntax: global varname */ + override Expr getASubExpression() { none() } - override Expr getASubExpression() { - none() - } - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } } /** An if statement, such as `if eggs: print("spam")` */ class If extends If_ { - /* syntax: if Expr: ... */ - override Stmt getASubStatement() { result = this.getAStmt() or result = this.getAnOrelse() } - override Expr getASubExpression() { - result = this.getTest() - } + override Expr getASubExpression() { result = this.getTest() } /** Whether this if statement takes the form `if __name__ == "__main__":` */ predicate isNameEqMain() { @@ -343,11 +238,13 @@ class If extends If_ { /** Whether this if statement starts with the keyword `elif` */ predicate isElif() { - /* The Python parser turns all elif chains into nested if-else statements. + /* + * The Python parser turns all elif chains into nested if-else statements. * An `elif` can be identified as it is the first statement in an `else` block * and it is not indented relative to its parent `if`. */ - exists(If i | + + exists(If i | i.getOrelse(0) = this and this.getLocation().getStartColumn() = i.getLocation().getStartColumn() ) @@ -365,74 +262,49 @@ class If extends If_ { not exists(this.getOrelse()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A nonlocal statement, such as `nonlocal var` */ class Nonlocal extends Nonlocal_ { - /* syntax: nonlocal varname */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } Variable getAVariable() { result.getScope() = this.getScope() and result.getId() = this.getAName() } - } /** A pass statement */ class Pass extends Pass_ { - /* syntax: pass */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - none() - } - + override Expr getASubExpression() { none() } } /** A print statement (Python 2 only), such as `print 0` */ class Print extends Print_ { - /* syntax: print Expr, ... */ - - override Stmt getASubStatement() { - none() - } + override Stmt getASubStatement() { none() } override Expr getASubExpression() { result = this.getAValue() or result = this.getDest() } - } /** A raise statement, such as `raise CompletelyDifferentException()` */ class Raise extends Raise_ { - /* syntax: raise Expr */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } + override Expr getASubExpression() { py_exprs(result, _, this, _) } - override Expr getASubExpression() { - py_exprs(result, _, this, _) - } - - /** The expression immediately following the `raise`, this is the + /** + * The expression immediately following the `raise`, this is the * exception raised, but not accounting for tuples in Python 2. */ Expr getException() { @@ -442,12 +314,10 @@ class Raise extends Raise_ { } /** The exception raised, accounting for tuples in Python 2. */ - Expr getRaised() - { - exists(Expr raw | - raw = this.getException() | - if (not major_version() = 2 or not exists(raw.(Tuple).getAnElt())) then - result = raw + Expr getRaised() { + exists(Expr raw | raw = this.getException() | + if not major_version() = 2 or not exists(raw.(Tuple).getAnElt()) + then result = raw else /* In Python 2 raising a tuple will result in the first element of the tuple being raised. */ result = raw.(Tuple).getElt(0) @@ -457,27 +327,16 @@ class Raise extends Raise_ { /** A return statement, such as return None */ class Return extends Return_ { - /* syntax: return Expr */ + override Stmt getASubStatement() { none() } - override Stmt getASubStatement() { - none() - } - - override Expr getASubExpression() { - result = this.getValue() - } - + override Expr getASubExpression() { result = this.getValue() } } /** A try statement */ class Try extends Try_ { - /* syntax: try: ... */ - - override Expr getASubExpression() { - none() - } + override Expr getASubExpression() { none() } override Stmt getASubStatement() { result = this.getAHandler() or @@ -486,14 +345,10 @@ class Try extends Try_ { result = this.getAnOrelse() } - override ExceptStmt getHandler(int i) { - result = Try_.super.getHandler(i) - } + override ExceptStmt getHandler(int i) { result = Try_.super.getHandler(i) } /** Gets an exception handler of this try statement. */ - override ExceptStmt getAHandler() { - result = Try_.super.getAHandler() - } + override ExceptStmt getAHandler() { result = Try_.super.getAHandler() } override Stmt getLastStatement() { result = this.getFinalbody().getLastItem().getLastStatement() @@ -501,23 +356,21 @@ class Try extends Try_ { not exists(this.getFinalbody()) and result = this.getOrelse().getLastItem().getLastStatement() or - not exists(this.getFinalbody()) and not exists(this.getOrelse()) and + not exists(this.getFinalbody()) and + not exists(this.getOrelse()) and result = this.getHandlers().getLastItem().getLastStatement() or - not exists(this.getFinalbody()) and not exists(this.getOrelse()) and not exists(this.getHandlers()) and + not exists(this.getFinalbody()) and + not exists(this.getOrelse()) and + not exists(this.getHandlers()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A while statement, such as `while parrot_resting():` */ class While extends While_ { - /* syntax: while Expr: ... */ - - override Expr getASubExpression() { - result = this.getTest() - } + override Expr getASubExpression() { result = this.getTest() } override Stmt getASubStatement() { result = this.getAStmt() or @@ -530,75 +383,44 @@ class While extends While_ { not exists(this.getOrelse()) and result = this.getBody().getLastItem().getLastStatement() } - } /** A with statement such as `with f as open("file"): text = f.read()` */ class With extends With_ { - /* syntax: with Expr as varname: ... */ - override Expr getASubExpression() { result = this.getContextExpr() or result = this.getOptionalVars() - } - - override Stmt getASubStatement() { - result = this.getAStmt() - } - - override Stmt getLastStatement() { - result = this.getBody().getLastItem().getLastStatement() } + override Stmt getASubStatement() { result = this.getAStmt() } + + override Stmt getLastStatement() { result = this.getBody().getLastItem().getLastStatement() } } /** A plain text used in a template is wrapped in a TemplateWrite statement */ class TemplateWrite extends TemplateWrite_ { + override Expr getASubExpression() { result = this.getValue() } - override Expr getASubExpression() { - result = this.getValue() - } - - override Stmt getASubStatement() { - none() - } - + override Stmt getASubStatement() { none() } } class AsyncFor extends For { - /* syntax: async for varname in Expr: ... */ - - AsyncFor() { - this.isAsync() - } - + AsyncFor() { this.isAsync() } } class AsyncWith extends With { - /* syntax: async with Expr as varname: ... */ - - AsyncWith() { - this.isAsync() - } - + AsyncWith() { this.isAsync() } } /** A list of statements */ class StmtList extends StmtList_ { - /** Whether this list of statements contains s */ predicate contains(AstNode a) { - exists(Stmt item | - item = this.getAnItem() | - item = a or item.contains(a) - ) + exists(Stmt item | item = this.getAnItem() | item = a or item.contains(a)) } Stmt getLastItem() { result = this.getItem(max(int i | exists(this.getItem(i)))) } - } - - diff --git a/python/ql/src/semmle/python/TestUtils.qll b/python/ql/src/semmle/python/TestUtils.qll index c94dcde0d78..a51d68dcf73 100644 --- a/python/ql/src/semmle/python/TestUtils.qll +++ b/python/ql/src/semmle/python/TestUtils.qll @@ -1,32 +1,29 @@ /* This file contains test-related utility functions */ - import python - /** Removes everything up to the occurrence of `sub` in the string `str` */ - -bindingset[str,sub] +bindingset[str, sub] string remove_prefix_before_substring(string str, string sub) { - exists(int index | - index = str.indexOf(sub) and - result = str.suffix(index) - ) - or - not exists(str.indexOf(sub)) and - result = str + exists(int index | + index = str.indexOf(sub) and + result = str.suffix(index) + ) + or + not exists(str.indexOf(sub)) and + result = str } -/** Removes the part of the `resources/lib` Python library path that may vary - * from machine to machine. */ - +/** + * Removes the part of the `resources/lib` Python library path that may vary + * from machine to machine. + */ string remove_library_prefix(Location loc) { - result = remove_prefix_before_substring(loc.toString(), "resources/lib") + result = remove_prefix_before_substring(loc.toString(), "resources/lib") } /** Returns the location of an AST node in compact form: `basename:line:column` */ string compact_location(AstNode a) { - exists(Location l | - l = a.getLocation() | + exists(Location l | l = a.getLocation() | result = l.getFile().getBaseName() + ":" + l.getStartLine() + ":" + l.getStartColumn() ) -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/Variables.qll b/python/ql/src/semmle/python/Variables.qll index 49f0f1aa4f1..df7ee2d07dd 100644 --- a/python/ql/src/semmle/python/Variables.qll +++ b/python/ql/src/semmle/python/Variables.qll @@ -1,24 +1,19 @@ - import python /** A variable, either a global or local variable (including parameters) */ class Variable extends @py_variable { - Variable() { exists(string name | variable(this, _, name) and - not name = "*" and not name = "$" + not name = "*" and + not name = "$" ) } /** Gets the identifier (name) of this variable */ - string getId() { - variable(this, _, result) - } + string getId() { variable(this, _, result) } - string toString() { - result = "Variable " + this.getId() - } + string toString() { result = "Variable " + this.getId() } /** Gets an access (load or store) of this variable */ Name getAnAccess() { @@ -28,103 +23,70 @@ class Variable extends @py_variable { } /** Gets a load of this variable */ - Name getALoad() { - result.uses(this) - } + Name getALoad() { result.uses(this) } /** Gets a store of this variable */ - Name getAStore() { - result.defines(this) - } + Name getAStore() { result.defines(this) } /** Gets a use of this variable */ - NameNode getAUse() { - result.uses(this) - } + NameNode getAUse() { result.uses(this) } /** Gets the scope of this variable */ - Scope getScope() { - variable(this, result, _) - } + Scope getScope() { variable(this, result, _) } - /** Whether there is an access to this variable outside + /** + * Whether there is an access to this variable outside * of its own scope. Usually occurs in nested functions * or for global variables. */ - predicate escapes() { - exists(Name n | n = this.getAnAccess() | n.getScope() != this.getScope()) - } + predicate escapes() { exists(Name n | n = this.getAnAccess() | n.getScope() != this.getScope()) } /** Whether this variable is a parameter */ - predicate isParameter() { - none() - } - - predicate isSelf() { - none() - } + predicate isParameter() { none() } + predicate isSelf() { none() } } /** A local (function or class) variable */ class LocalVariable extends Variable { - LocalVariable() { exists(Scope s | s = this.getScope() | s instanceof Function or s instanceof Class) } - override string toString() { - result = "Local Variable " + this.getId() - } + override string toString() { result = "Local Variable " + this.getId() } /** Whether this variable is a parameter */ - override predicate isParameter() { - exists(Parameter p | this.getAnAccess() = p) - } + override predicate isParameter() { exists(Parameter p | this.getAnAccess() = p) } /** Holds if this variable is the first parameter of a method. It is not necessarily called "self" */ override predicate isSelf() { - exists(Function f, Parameter self | + exists(Function f, Parameter self | this.getAnAccess() = self and - f.isMethod() and f.getArg(0) = self + f.isMethod() and + f.getArg(0) = self ) } - } -/** A local variable that uses "load fast" semantics, for lookup: - * If the variable is undefined, then raise an exception. +/** + * A local variable that uses "load fast" semantics, for lookup: + * If the variable is undefined, then raise an exception. */ class FastLocalVariable extends LocalVariable { - - FastLocalVariable() { - this.getScope() instanceof FastLocalsFunction - } - + FastLocalVariable() { this.getScope() instanceof FastLocalsFunction } } -/** A local variable that uses "load name" semantics, for lookup: +/** + * A local variable that uses "load name" semantics, for lookup: * If the variable is undefined, then lookup the value in globals(). */ class NameLocalVariable extends LocalVariable { - - NameLocalVariable() { - not this instanceof FastLocalVariable - } - + NameLocalVariable() { not this instanceof FastLocalVariable } } /** A global (module-level) variable */ class GlobalVariable extends Variable { + GlobalVariable() { exists(Module m | m = this.getScope()) } - GlobalVariable() { - exists(Module m | m = this.getScope()) - } - - override string toString() { - result = "Global Variable " + this.getId() - } - + override string toString() { result = "Global Variable " + this.getId() } } - - diff --git a/python/ql/src/semmle/python/dataflow/Files.qll b/python/ql/src/semmle/python/dataflow/Files.qll index 651b7a93850..467a8bec29e 100644 --- a/python/ql/src/semmle/python/dataflow/Files.qll +++ b/python/ql/src/semmle/python/dataflow/Files.qll @@ -11,7 +11,7 @@ class OpenFileConfiguration extends TaintTracking::Configuration { OpenFileConfiguration() { this = "Open file configuration" } override predicate isSource(DataFlow::Node src, TaintKind kind) { - theOpenFunction().(FunctionObject).getACall() = src.asCfgNode() and + src.asCfgNode() = Value::named("open").getACall() and kind instanceof OpenFile } diff --git a/python/ql/src/semmle/python/dataflow/Implementation.qll b/python/ql/src/semmle/python/dataflow/Implementation.qll index 457078a68c7..571a831b81f 100644 --- a/python/ql/src/semmle/python/dataflow/Implementation.qll +++ b/python/ql/src/semmle/python/dataflow/Implementation.qll @@ -57,8 +57,8 @@ private newtype TAttributePath = * It might make sense to add another level, attribute of attribute. * But some experimentation would be needed. */ - TAttribute(string name) { exists(Attribute a | a.getName() = name) } + TAttribute(string name) { exists(Attribute a | a.getName() = name) } /** * The attribute of the tracked value holding the taint. @@ -445,9 +445,8 @@ class TaintTrackingImplementation extends string { context = TNoParam() and src = TTaintTrackingNode_(retval, TNoParam(), path, kind, this) and node.asCfgNode() = call and - retval.asCfgNode() = any(Return ret | ret.getScope() = pyfunc.getScope()) - .getValue() - .getAFlowNode() + retval.asCfgNode() = + any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode() ) and edgeLabel = "return" } @@ -469,9 +468,8 @@ class TaintTrackingImplementation extends string { this.callContexts(call, src, pyfunc, context, callee) and retnode = TTaintTrackingNode_(retval, callee, path, kind, this) and node.asCfgNode() = call and - retval.asCfgNode() = any(Return ret | ret.getScope() = pyfunc.getScope()) - .getValue() - .getAFlowNode() + retval.asCfgNode() = + any(Return ret | ret.getScope() = pyfunc.getScope()).getValue().getAFlowNode() ) and edgeLabel = "call" } @@ -965,11 +963,12 @@ private TaintKind taint_at_depth(SequenceKind parent_kind, int depth) { or // recursive case depth > 1 and - result = taint_at_depth(parent_kind.getMember(), depth-1) + result = taint_at_depth(parent_kind.getMember(), depth - 1) ) } -/** Helper predicate for taintedMultiAssignment +/** + * Helper predicate for taintedMultiAssignment * * Returns the `depth` the elements that are assigned to `left_defn` with iterable unpacking has, * compared to `left_parent`. Special care is taken for `StarredNode` that is assigned a sequence of items. @@ -984,9 +983,7 @@ int iterable_unpacking_descent(SequenceNode left_parent, ControlFlowNode left_de exists(Assign a | a.getATarget().getASubExpression*().getAFlowNode() = left_parent) and left_parent.getAnElement() = left_defn and // Handle `a, *b = some_iterable` - if left_defn instanceof StarredNode - then result = 0 - else result = 1 + if left_defn instanceof StarredNode then result = 0 else result = 1 or result = 1 + iterable_unpacking_descent(left_parent.getAnElement(), left_defn) } diff --git a/python/ql/src/semmle/python/dependencies/Dependencies.qll b/python/ql/src/semmle/python/dependencies/Dependencies.qll index bda3b45f323..6d2052f0dfb 100644 --- a/python/ql/src/semmle/python/dependencies/Dependencies.qll +++ b/python/ql/src/semmle/python/dependencies/Dependencies.qll @@ -1,13 +1,14 @@ - import python import semmle.python.dependencies.DependencyKind private predicate importDependency(Object target, AstNode source) { - source.getScope() != target.getOrigin() and /* Imports of own module are ignored */ + source.getScope() != target.getOrigin() and + /* Imports of own module are ignored */ ( exists(ModuleObject importee, ImportingStmt imp_stmt | source = imp_stmt and - importee = target | + importee = target + | exists(ImportMember im | imp_stmt.contains(im) | importee.importedAs(im.getImportedModuleName()) ) @@ -23,11 +24,9 @@ private predicate importDependency(Object target, AstNode source) { ) or /* from m import name, where m.name is not a submodule */ - exists(PythonModuleObject importee, ImportingStmt imp_stmt | - source = imp_stmt | + exists(PythonModuleObject importee, ImportingStmt imp_stmt | source = imp_stmt | exists(ImportMember im | imp_stmt.contains(im) | - importee.importedAs(im.getModule().(ImportExpr).getImportedModuleName()) - and + importee.importedAs(im.getModule().(ImportExpr).getImportedModuleName()) and defn_of_module_attribute(target, importee.getModule(), im.getName()) ) ) @@ -35,16 +34,12 @@ private predicate importDependency(Object target, AstNode source) { } class PythonImport extends DependencyKind { - - PythonImport() { - this = "import" - } + PythonImport() { this = "import" } override predicate isADependency(AstNode source, Object target) { this = this and importDependency(target, source) } - } private predicate interesting(Object target) { @@ -58,10 +53,7 @@ private predicate interesting(Object target) { } class PythonUse extends DependencyKind { - - PythonUse() { - this = "use" - } + PythonUse() { this = "use" } override predicate isADependency(AstNode source, Object target) { interesting(target) and @@ -71,22 +63,20 @@ class PythonUse extends DependencyKind { use.getNode() = source and use.refersTo(obj) and use.isLoad() - | + | interesting(obj) and target = obj - ) - and + ) and not has_more_specific_dependency_source(source) } - } -/** Whether there is a more specific dependency source than this one. +/** + * Whether there is a more specific dependency source than this one. * E.g. if the expression pack.mod.func is a dependency on the function 'func' in 'pack.mod' * don't make pack.mod depend on the module 'pack.mod' */ private predicate has_more_specific_dependency_source(Expr e) { - exists(Attribute member | - member.getObject() = e | + exists(Attribute member | member.getObject() = e | attribute_access_dependency(_, member) or has_more_specific_dependency_source(member) @@ -94,35 +84,25 @@ private predicate has_more_specific_dependency_source(Expr e) { } class PythonInheritance extends DependencyKind { - - PythonInheritance() { - this = "inheritance" - } + PythonInheritance() { this = "inheritance" } override predicate isADependency(AstNode source, Object target) { this = this and - exists(ClassObject cls | - source = cls.getOrigin() - | + exists(ClassObject cls | source = cls.getOrigin() | target = cls.getASuperType() or target = cls.getAnInferredType() ) } - } class PythonAttribute extends DependencyKind { - - PythonAttribute() { - this = "attribute" - } + PythonAttribute() { this = "attribute" } override predicate isADependency(AstNode source, Object target) { this = this and attribute_access_dependency(target, source) } - } private predicate attribute_access_dependency(Object target, AstNode source) { @@ -133,30 +113,23 @@ private predicate attribute_access_dependency(Object target, AstNode source) { } private predicate use_of_attribute(Attribute attr, Scope s, string name) { - exists(AttrNode cfg | - cfg.isLoad() and cfg.getNode() = attr - | - exists(Object obj | - cfg.getObject(name).refersTo(obj) | + exists(AttrNode cfg | cfg.isLoad() and cfg.getNode() = attr | + exists(Object obj | cfg.getObject(name).refersTo(obj) | s = obj.(PythonModuleObject).getModule() or s = obj.(ClassObject).getPyClass() - ) or - exists(ClassObject cls | - cfg.getObject(name).refersTo(_, cls, _) | - s = cls.getPyClass() ) + or + exists(ClassObject cls | cfg.getObject(name).refersTo(_, cls, _) | s = cls.getPyClass()) ) or - exists(SelfAttributeRead sar | - sar = attr | + exists(SelfAttributeRead sar | sar = attr | sar.getClass() = s and sar.getName() = name ) } private predicate defn_of_attribute(Object target, Scope s, string name) { - exists(Assign asgn | - target.(ControlFlowNode).getNode() = asgn | + exists(Assign asgn | target.(ControlFlowNode).getNode() = asgn | defn_of_instance_attribute(asgn, s, name) or defn_of_class_attribute(asgn, s, name) @@ -165,13 +138,14 @@ private predicate defn_of_attribute(Object target, Scope s, string name) { defn_of_module_attribute(target, s, name) } -/* Whether asgn defines an instance attribute, that is does +/* + * Whether asgn defines an instance attribute, that is does * asgn take the form self.name = ... where self is an instance * of class c and asgn is not a redefinition. */ + private predicate defn_of_instance_attribute(Assign asgn, Class c, string name) { - exists(SelfAttributeStore sas | - asgn.getATarget() = sas | + exists(SelfAttributeStore sas | asgn.getATarget() = sas | sas.getClass() = c and sas.getName() = name and not exists(SelfAttributeStore in_init | diff --git a/python/ql/src/semmle/python/dependencies/DependencyKind.qll b/python/ql/src/semmle/python/dependencies/DependencyKind.qll index 791723042ac..ae91593d251 100644 --- a/python/ql/src/semmle/python/dependencies/DependencyKind.qll +++ b/python/ql/src/semmle/python/dependencies/DependencyKind.qll @@ -3,7 +3,6 @@ import semmle.python.dependencies.Dependencies /** * A library describing an abstract mechanism for representing dependency categories. */ - /* * A DependencyCategory is a unique string key used by Architect to identify different categories * of dependencies that might be viewed independently. @@ -12,20 +11,17 @@ import semmle.python.dependencies.Dependencies * accepted by Architect. *

    */ -abstract class DependencyKind extends string { +abstract class DependencyKind extends string { bindingset[this] - DependencyKind() { - this = this - } + DependencyKind() { this = this } /* Tech inventory interface */ /** - * Identify dependencies associated with this category. - *

    - * The source element is the source of the dependency. - *

    - */ + * Identify dependencies associated with this category. + *

    + * The source element is the source of the dependency. + *

    + */ abstract predicate isADependency(AstNode source, Object target); - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/dependencies/TechInventory.qll b/python/ql/src/semmle/python/dependencies/TechInventory.qll index 8ca97f56178..43a7cf55ec2 100644 --- a/python/ql/src/semmle/python/dependencies/TechInventory.qll +++ b/python/ql/src/semmle/python/dependencies/TechInventory.qll @@ -2,49 +2,41 @@ import python import semmle.python.dependencies.Dependencies import semmle.python.dependencies.DependencyKind -/** Combine the source-file and package into a single string: +/** + * Combine the source-file and package into a single string: * /path/to/file.py<|>package-name-and-version */ string munge(File sourceFile, ExternalPackage package) { - result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>" + package.getVersion() or - not exists(package.getVersion()) and result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>unknown" + result = + "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>" + package.getVersion() + or + not exists(package.getVersion()) and + result = "/" + sourceFile.getRelativePath() + "<|>" + package.getName() + "<|>unknown" } abstract class ExternalPackage extends Object { - - ExternalPackage() { - this instanceof ModuleObject - } + ExternalPackage() { this instanceof ModuleObject } abstract string getName(); abstract string getVersion(); - Object getAttribute(string name) { - result = this.(ModuleObject).attr(name) - } - - PackageObject getPackage() { - result = this.(ModuleObject).getPackage() - } + Object getAttribute(string name) { result = this.(ModuleObject).attr(name) } + PackageObject getPackage() { result = this.(ModuleObject).getPackage() } } bindingset[text] -private predicate is_version(string text) { - text.regexpMatch("\\d+\\.\\d+(\\.\\d+)?([ab]\\d+)?") -} +private predicate is_version(string text) { text.regexpMatch("\\d+\\.\\d+(\\.\\d+)?([ab]\\d+)?") } bindingset[v] private string version_format(float v) { - exists(int i, int f | - i = (v+0.05).floor() and f = ((v+0.05-i)*10).floor() | + exists(int i, int f | i = (v + 0.05).floor() and f = ((v + 0.05 - i) * 10).floor() | result = i + "." + f ) } class DistPackage extends ExternalPackage { - DistPackage() { exists(Folder parent | parent = this.(ModuleObject).getPath().getParent() and @@ -56,12 +48,13 @@ class DistPackage extends ExternalPackage { ) } - /* We don't extract the meta-data for dependencies (yet), so make a best guess from the source - * https://www.python.org/dev/peps/pep-0396/ + /* + * We don't extract the meta-data for dependencies (yet), so make a best guess from the source + * https://www.python.org/dev/peps/pep-0396/ */ + private predicate possibleVersion(string version, int priority) { - exists(Object v | - v = this.getAttribute("__version__") and priority = 3 | + exists(Object v | v = this.getAttribute("__version__") and priority = 3 | version = v.(StringObject).getText() and is_version(version) or version = version_format(v.(NumericObject).floatValue()) @@ -71,33 +64,36 @@ class DistPackage extends ExternalPackage { or exists(SequenceObject tuple, NumericObject major, NumericObject minor, string base_version | this.getAttribute("version_info") = tuple and - major = tuple.getInferredElement(0) and minor = tuple.getInferredElement(1) and - base_version = major.intValue() + "." + minor.intValue() | + major = tuple.getInferredElement(0) and + minor = tuple.getInferredElement(1) and + base_version = major.intValue() + "." + minor.intValue() + | version = base_version + "." + tuple.getBuiltinElement(2).(NumericObject).intValue() or not exists(tuple.getBuiltinElement(2)) and version = base_version - ) and priority = 2 + ) and + priority = 2 or - exists(string v | - v.toLowerCase() = "version" | + exists(string v | v.toLowerCase() = "version" | is_version(version) and version = this.getAttribute(v).(StringObject).getText() - ) and priority = 1 + ) and + priority = 1 } override string getVersion() { this.possibleVersion(result, max(int priority | this.possibleVersion(_, priority))) } - override string getName() { - result = this.(ModuleObject).getShortName() - } + override string getName() { result = this.(ModuleObject).getShortName() } predicate fromSource(Object src) { exists(ModuleObject m | m.getModule() = src.(ControlFlowNode).getEnclosingModule() or - src = m | - m = this or + src = m + | + m = this + or m.getPackage+() = this and not exists(DistPackage inter | m.getPackage*() = inter and @@ -105,12 +101,10 @@ class DistPackage extends ExternalPackage { ) ) } - } predicate dependency(AstNode src, DistPackage package) { - exists(DependencyKind cat, Object target | - cat.isADependency(src, target) | + exists(DependencyKind cat, Object target | cat.isADependency(src, target) | package.fromSource(target) ) } diff --git a/python/ql/src/semmle/python/essa/Definitions.qll b/python/ql/src/semmle/python/essa/Definitions.qll index c21e8148582..6ecb3f6b50d 100644 --- a/python/ql/src/semmle/python/essa/Definitions.qll +++ b/python/ql/src/semmle/python/essa/Definitions.qll @@ -1,6 +1,7 @@ import python -/* Classification of variables. These should be non-overlapping and complete. +/* + * Classification of variables. These should be non-overlapping and complete. * * Function local variables - Non escaping variables in a function, except 'self' * Self variables - The 'self' variable for a method. @@ -11,31 +12,24 @@ import python * Escaping globals -- Global variables that have definitions and at least one of those definitions is in another scope. */ - /** A source language variable, to be converted into a set of SSA variables. */ +/** A source language variable, to be converted into a set of SSA variables. */ abstract class SsaSourceVariable extends @py_variable { - SsaSourceVariable() { /* Exclude `True`, `False` and `None` */ not this.(Variable).getALoad() instanceof NameConstant } /** Gets the name of this variable */ - string getName() { - variable(this, _, result) - } + string getName() { variable(this, _, result) } - Scope getScope() { - variable(this, result, _) - } + Scope getScope() { variable(this, result, _) } /** Gets an implicit use of this variable */ abstract ControlFlowNode getAnImplicitUse(); abstract ControlFlowNode getScopeEntryDefinition(); - string toString() { - result = "SsaSourceVariable " + this.getName() - } + string toString() { result = "SsaSourceVariable " + this.getName() } /** Gets a use of this variable, either explicit or implicit. */ ControlFlowNode getAUse() { @@ -43,14 +37,18 @@ abstract class SsaSourceVariable extends @py_variable { or result = this.getAnImplicitUse() or - /* `import *` is a definition of *all* variables, so must be a use as well, for pass-through + /* + * `import *` is a definition of *all* variables, so must be a use as well, for pass-through * once we have established that a variable is not redefined. */ + SsaSource::import_star_refinement(this, result, _) or - /* Add a use at the end of scope for all variables to keep them live + /* + * Add a use at the end of scope for all variables to keep them live * This is necessary for taint-tracking. */ + result = this.getScope().getANormalExit() } @@ -73,15 +71,18 @@ abstract class SsaSourceVariable extends @py_variable { SsaSource::with_definition(this, def) } - /** Holds if `def` defines an ESSA variable for this variable in such a way + /** + * Holds if `def` defines an ESSA variable for this variable in such a way * that the new variable is a refinement in some way of the variable used at `use`. */ predicate hasRefinement(ControlFlowNode use, ControlFlowNode def) { - this.hasDefiningNode(_) and /* Can't have a refinement unless there is a definition */ + this.hasDefiningNode(_) and + /* Can't have a refinement unless there is a definition */ refinement(this, use, def) } - /** Holds if the edge `pred`->`succ` defines an ESSA variable for this variable in such a way + /** + * Holds if the edge `pred`->`succ` defines an ESSA variable for this variable in such a way * that the new variable is a refinement in some way of the variable used at `use`. */ predicate hasRefinementEdge(ControlFlowNode use, BasicBlock pred, BasicBlock succ) { @@ -100,7 +101,6 @@ abstract class SsaSourceVariable extends @py_variable { } abstract CallNode redefinedAtCallSite(); - } private predicate refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { @@ -119,9 +119,7 @@ private predicate refinement(SsaSourceVariable v, ControlFlowNode use, ControlFl def = v.redefinedAtCallSite() and def = use } - class FunctionLocalVariable extends SsaSourceVariable { - FunctionLocalVariable() { this.(LocalVariable).getScope() instanceof Function and not this instanceof NonLocalVariable @@ -132,8 +130,7 @@ class FunctionLocalVariable extends SsaSourceVariable { } override ControlFlowNode getScopeEntryDefinition() { - exists(Scope s | - s.getEntryNode() = result | + exists(Scope s | s.getEntryNode() = result | s = this.(LocalVariable).getScope() and not this.(LocalVariable).isParameter() or @@ -143,11 +140,9 @@ class FunctionLocalVariable extends SsaSourceVariable { } override CallNode redefinedAtCallSite() { none() } - } class NonLocalVariable extends SsaSourceVariable { - NonLocalVariable() { exists(Function f | this.(LocalVariable).getScope() = f and @@ -169,37 +164,27 @@ class NonLocalVariable extends SsaSourceVariable { this.(LocalVariable).getScope().getEntryNode() = result } - pragma [noinline] - Scope scope_as_local_variable() { - result = this.(LocalVariable).getScope() - } + pragma[noinline] + Scope scope_as_local_variable() { result = this.(LocalVariable).getScope() } override CallNode redefinedAtCallSite() { result.getScope().getScope*() = this.scope_as_local_variable() } - } class ClassLocalVariable extends SsaSourceVariable { + ClassLocalVariable() { this.(LocalVariable).getScope() instanceof Class } - ClassLocalVariable() { - this.(LocalVariable).getScope() instanceof Class - } - - override ControlFlowNode getAnImplicitUse() { - none() - } + override ControlFlowNode getAnImplicitUse() { none() } override ControlFlowNode getScopeEntryDefinition() { result = this.(LocalVariable).getScope().getEntryNode() } override CallNode redefinedAtCallSite() { none() } - } class BuiltinVariable extends SsaSourceVariable { - BuiltinVariable() { this instanceof GlobalVariable and not exists(this.(Variable).getAStore()) and @@ -208,20 +193,14 @@ class BuiltinVariable extends SsaSourceVariable { not exists(ImportStar is | is.getScope() = this.(Variable).getScope()) } - override ControlFlowNode getAnImplicitUse() { - none() - } + override ControlFlowNode getAnImplicitUse() { none() } - override ControlFlowNode getScopeEntryDefinition() { - none() - } + override ControlFlowNode getScopeEntryDefinition() { none() } override CallNode redefinedAtCallSite() { none() } - } class ModuleVariable extends SsaSourceVariable { - ModuleVariable() { this instanceof GlobalVariable and ( @@ -235,10 +214,8 @@ class ModuleVariable extends SsaSourceVariable { ) } - pragma [noinline] - CallNode global_variable_callnode() { - result.getScope() = this.(GlobalVariable).getScope() - } + pragma[noinline] + CallNode global_variable_callnode() { result.getScope() = this.(GlobalVariable).getScope() } pragma[noinline] ImportMemberNode global_variable_import() { @@ -251,8 +228,7 @@ class ModuleVariable extends SsaSourceVariable { or result = global_variable_import() or - exists(ImportTimeScope scope | - scope.entryEdge(result, _) | + exists(ImportTimeScope scope | scope.entryEdge(result, _) | this = scope.getOuterVariable(_) or this.(Variable).getAUse().getScope() = scope ) @@ -264,14 +240,14 @@ class ModuleVariable extends SsaSourceVariable { ) or exists(ImportTimeScope s | - result = s.getANormalExit() and this.(Variable).getScope() = s and + result = s.getANormalExit() and + this.(Variable).getScope() = s and implicit_definition(this) ) } override ControlFlowNode getScopeEntryDefinition() { - exists(Scope s | - s.getEntryNode() = result | + exists(Scope s | s.getEntryNode() = result | /* Module entry point */ this.(GlobalVariable).getScope() = s or @@ -282,31 +258,28 @@ class ModuleVariable extends SsaSourceVariable { this.(GlobalVariable).getAUse().getScope() = s ) or - exists(ImportTimeScope scope | - scope.entryEdge(_, result) | + exists(ImportTimeScope scope | scope.entryEdge(_, result) | this = scope.getOuterVariable(_) or this.(Variable).getAUse().getScope() = scope ) } override CallNode redefinedAtCallSite() { none() } - } class NonEscapingGlobalVariable extends ModuleVariable { - NonEscapingGlobalVariable() { this instanceof GlobalVariable and exists(this.(Variable).getAStore()) and not variable_or_attribute_defined_out_of_scope(this) } - } class EscapingGlobalVariable extends ModuleVariable { - EscapingGlobalVariable() { - this instanceof GlobalVariable and exists(this.(Variable).getAStore()) and variable_or_attribute_defined_out_of_scope(this) + this instanceof GlobalVariable and + exists(this.(Variable).getAStore()) and + variable_or_attribute_defined_out_of_scope(this) } override ControlFlowNode getAnImplicitUse() { @@ -328,36 +301,25 @@ class EscapingGlobalVariable extends ModuleVariable { result = this.innerScope().getEntryNode() } - pragma [noinline] - Scope scope_as_global_variable() { - result = this.(GlobalVariable).getScope() - } + pragma[noinline] + Scope scope_as_global_variable() { result = this.(GlobalVariable).getScope() } override CallNode redefinedAtCallSite() { result.(CallNode).getScope().getScope*() = this.scope_as_global_variable() } - } class EscapingAssignmentGlobalVariable extends EscapingGlobalVariable { - EscapingAssignmentGlobalVariable() { exists(NameNode n | n.defines(this) and not n.getScope() = this.getScope()) } - } - class SpecialSsaSourceVariable extends SsaSourceVariable { - - SpecialSsaSourceVariable() { - variable(this, _, "*") or variable(this, _, "$") - } + SpecialSsaSourceVariable() { variable(this, _, "*") or variable(this, _, "$") } override ControlFlowNode getAnImplicitUse() { - exists(ImportTimeScope s | - result = s.getANormalExit() and this.getScope() = s - ) + exists(ImportTimeScope s | result = s.getANormalExit() and this.getScope() = s) } override ControlFlowNode getScopeEntryDefinition() { @@ -365,31 +327,31 @@ class SpecialSsaSourceVariable extends SsaSourceVariable { this.getScope().getEntryNode() = result } - pragma [noinline] - Scope scope_as_global_variable() { - result = this.(GlobalVariable).getScope() - } + pragma[noinline] + Scope scope_as_global_variable() { result = this.(GlobalVariable).getScope() } override CallNode redefinedAtCallSite() { result.(CallNode).getScope().getScope*() = this.scope_as_global_variable() } - } /** Holds if this variable is implicitly defined */ private predicate implicit_definition(Variable v) { - v.getId() = "*" or v.getId() = "$" - or + v.getId() = "*" or + v.getId() = "$" or exists(ImportStar is | is.getScope() = v.getScope()) } private predicate variable_or_attribute_defined_out_of_scope(Variable v) { exists(NameNode n | n.defines(v) and not n.getScope() = v.getScope()) or - exists(AttrNode a | a.isStore() and a.getObject() = v.getAUse() and not a.getScope() = v.getScope()) + exists(AttrNode a | + a.isStore() and a.getObject() = v.getAUse() and not a.getScope() = v.getScope() + ) } private predicate class_with_global_metaclass(Class cls, GlobalVariable metaclass) { - metaclass.getId() = "__metaclass__" and major_version() = 2 and + metaclass.getId() = "__metaclass__" and + major_version() = 2 and cls.getEnclosingModule() = metaclass.getScope() } diff --git a/python/ql/src/semmle/python/essa/Essa.qll b/python/ql/src/semmle/python/essa/Essa.qll index fdfc2fb92fe..4608499be46 100644 --- a/python/ql/src/semmle/python/essa/Essa.qll +++ b/python/ql/src/semmle/python/essa/Essa.qll @@ -6,46 +6,35 @@ import python private import SsaCompute import semmle.python.essa.Definitions - /** An (enhanced) SSA variable derived from `SsaSourceVariable`. */ class EssaVariable extends TEssaDefinition { - /** Gets the (unique) definition of this variable. */ - EssaDefinition getDefinition() { - this = result - } + EssaDefinition getDefinition() { this = result } - /** Gets a use of this variable, where a "use" is defined by + /** + * Gets a use of this variable, where a "use" is defined by * `SsaSourceVariable.getAUse()`. * Note that this differs from `EssaVariable.getASourceUse()`. */ - ControlFlowNode getAUse() { - result = this.getDefinition().getAUse() - } + ControlFlowNode getAUse() { result = this.getDefinition().getAUse() } /** Gets the source variable from which this variable is derived. */ - SsaSourceVariable getSourceVariable() { - result = this.getDefinition().getSourceVariable() - } + SsaSourceVariable getSourceVariable() { result = this.getDefinition().getSourceVariable() } /** Gets the name of this variable. */ - string getName() { - result = this.getSourceVariable().getName() - } + string getName() { result = this.getSourceVariable().getName() } - string toString() { - result = "SSA variable " + this.getName() - } + string toString() { result = "SSA variable " + this.getName() } - /** Gets a string representation of this variable. + /** + * Gets a string representation of this variable. * WARNING: The format of this may change and it may be very inefficient to compute. * To used for debugging and testing only. */ - string getRepresentation() { - result = this.getSourceVariable().getName() + "_" + var_rank(this) - } + string getRepresentation() { result = this.getSourceVariable().getName() + "_" + var_rank(this) } - /** Gets a use of this variable, where a "use" is defined by + /** + * Gets a use of this variable, where a "use" is defined by * `SsaSourceVariable.getASourceUse()`. * Note that this differs from `EssaVariable.getAUse()`. */ @@ -63,23 +52,21 @@ class EssaVariable extends TEssaDefinition { } /** Gets the scope of this variable. */ - Scope getScope() { - result = this.getDefinition().getScope() - } + Scope getScope() { result = this.getDefinition().getScope() } - /** Holds if this the meta-variable for a scope. + /** + * Holds if this the meta-variable for a scope. * This is used to attach attributes for undeclared variables implicitly * defined by `from ... import *` and the like. */ - predicate isMetaVariable() { - this.getName() = "$" - } - + predicate isMetaVariable() { this.getName() = "$" } } -/* Helper for location_string +/* + * Helper for location_string * NOTE: This is Python specific, to make `getRepresentation()` portable will require further work. */ + private int exception_handling(BasicBlock b) { b.reachesExit() and result = 0 or @@ -91,14 +78,15 @@ pragma[noinline] private string location_string(EssaVariable v) { exists(EssaDefinition def, BasicBlock b, int index, int line, int col | def = v.getDefinition() and - (if b.getNode(0).isNormalExit() then - line = 100000 and col = 0 - else - b.hasLocationInfo(_, line, col, _, _) + ( + if b.getNode(0).isNormalExit() + then line = 100000 and col = 0 + else b.hasLocationInfo(_, line, col, _, _) ) and /* Add large numbers to values to prevent 1000 sorting before 99 */ - result = (line + 100000) + ":" + (col*2 + 10000 + exception_handling(b)) + ":" + (index + 100003) - | + result = + (line + 100000) + ":" + (col * 2 + 10000 + exception_handling(b)) + ":" + (index + 100003) + | def = TEssaNodeDefinition(_, b, index) or def = TEssaNodeRefinement(_, b, index) @@ -119,37 +107,31 @@ private int var_rank(EssaVariable v) { exists(int r, SsaSourceVariable var | var = v.getSourceVariable() and var_index(v) = rank[r](EssaVariable x | x.getSourceVariable() = var | var_index(x)) and - result = r-1 + result = r - 1 ) } /** Underlying IPA type for EssaDefinition and EssaVariable. */ -private cached newtype TEssaDefinition = +cached +private newtype TEssaDefinition = TEssaNodeDefinition(SsaSourceVariable v, BasicBlock b, int i) { EssaDefinitions::variableDefinition(v, _, b, _, i) - } - or + } or TEssaNodeRefinement(SsaSourceVariable v, BasicBlock b, int i) { EssaDefinitions::variableRefinement(v, _, b, _, i) - } - or + } or TEssaEdgeDefinition(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { EssaDefinitions::piNode(v, pred, succ) - } - or - TPhiFunction(SsaSourceVariable v, BasicBlock b) { - EssaDefinitions::phiNode(v, b) - } + } or + TPhiFunction(SsaSourceVariable v, BasicBlock b) { EssaDefinitions::phiNode(v, b) } -/** Definition of an extended-SSA (ESSA) variable. +/** + * Definition of an extended-SSA (ESSA) variable. * There is exactly one definition for each variable, * and exactly one variable for each definition. */ abstract class EssaDefinition extends TEssaDefinition { - - string toString() { - result = "EssaDefinition" - } + string toString() { result = "EssaDefinition" } /** Gets the source variable for which this a definition, either explicit or implicit. */ abstract SsaSourceVariable getSourceVariable(); @@ -160,7 +142,8 @@ abstract class EssaDefinition extends TEssaDefinition { /** Holds if this definition reaches the end of `b`. */ abstract predicate reachesEndOfBlock(BasicBlock b); - /** Gets the location of a control flow node that is indicative of this definition. + /** + * Gets the location of a control flow node that is indicative of this definition. * Since definitions may occur on edges of the control flow graph, the given location may * be imprecise. * Distinct `EssaDefinitions` may return the same ControlFlowNode even for @@ -168,29 +151,26 @@ abstract class EssaDefinition extends TEssaDefinition { */ abstract Location getLocation(); - /** Gets a representation of this SSA definition for debugging purposes. - * Since this is primarily for debugging and testing, performance may be poor. */ + /** + * Gets a representation of this SSA definition for debugging purposes. + * Since this is primarily for debugging and testing, performance may be poor. + */ abstract string getRepresentation(); abstract Scope getScope(); - EssaVariable getVariable() { - result.getDefinition() = this - } + EssaVariable getVariable() { result.getDefinition() = this } abstract BasicBlock getBasicBlock(); - } -/** An ESSA definition corresponding to an edge refinement of the underlying variable. +/** + * An ESSA definition corresponding to an edge refinement of the underlying variable. * For example, the edges leaving a test on a variable both represent refinements of that * variable. On one edge the test is true, on the other it is false. */ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { - - override string toString() { - result = "SSA filter definition" - } + override string toString() { result = "SSA filter definition" } boolean getSense() { this.getPredecessor().getATrueSuccessor() = this.getSuccessor() and result = true @@ -198,19 +178,13 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { this.getPredecessor().getAFalseSuccessor() = this.getSuccessor() and result = false } - override SsaSourceVariable getSourceVariable() { - this = TEssaEdgeDefinition(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaEdgeDefinition(result, _, _) } /** Gets the basic block preceding the edge on which this refinement occurs. */ - BasicBlock getPredecessor() { - this = TEssaEdgeDefinition(_, result, _) - } + BasicBlock getPredecessor() { this = TEssaEdgeDefinition(_, result, _) } /** Gets the basic block succeeding the edge on which this refinement occurs. */ - BasicBlock getSuccessor() { - this = TEssaEdgeDefinition(_, _, result) - } + BasicBlock getSuccessor() { this = TEssaEdgeDefinition(_, _, result) } override ControlFlowNode getAUse() { SsaDefinitions::reachesUse(this.getSourceVariable(), this.getSuccessor(), piIndex(), result) @@ -220,13 +194,11 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { SsaDefinitions::reachesEndOfBlock(this.getSourceVariable(), this.getSuccessor(), piIndex(), b) } - override Location getLocation() { - result = this.getSuccessor().getNode(0).getLocation() - } + override Location getLocation() { result = this.getSuccessor().getNode(0).getLocation() } /** Gets the SSA variable to which this refinement applies. */ EssaVariable getInput() { - exists(SsaSourceVariable var , EssaDefinition def | + exists(SsaSourceVariable var, EssaDefinition def | var = this.getSourceVariable() and var = def.getSourceVariable() and def.reachesEndOfBlock(this.getPredecessor()) and @@ -239,19 +211,13 @@ class EssaEdgeRefinement extends EssaDefinition, TEssaEdgeDefinition { } /** Gets the scope of the variable defined by this definition. */ - override Scope getScope() { - result = this.getPredecessor().getScope() - } - - override BasicBlock getBasicBlock(){ - result = this.getSuccessor() - } + override Scope getScope() { result = this.getPredecessor().getScope() } + override BasicBlock getBasicBlock() { result = this.getSuccessor() } } /** A Phi-function as specified in classic SSA form. */ class PhiFunction extends EssaDefinition, TPhiFunction { - override ControlFlowNode getAUse() { SsaDefinitions::reachesUse(this.getSourceVariable(), this.getBasicBlock(), phiIndex(), result) } @@ -260,9 +226,7 @@ class PhiFunction extends EssaDefinition, TPhiFunction { SsaDefinitions::reachesEndOfBlock(this.getSourceVariable(), this.getBasicBlock(), phiIndex(), b) } - override SsaSourceVariable getSourceVariable() { - this = TPhiFunction(result, _) - } + override SsaSourceVariable getSourceVariable() { this = TPhiFunction(result, _) } /** Gets an input refinement that exists on one of the incoming edges to this phi node. */ private EssaEdgeRefinement inputEdgeRefinement(BasicBlock pred) { @@ -290,37 +254,29 @@ class PhiFunction extends EssaDefinition, TPhiFunction { } /** Gets the input variable for this phi node on the edge `pred` -> `this.getBasicBlock()`, if any. */ - cached EssaVariable getInput(BasicBlock pred) { + cached + EssaVariable getInput(BasicBlock pred) { result.getDefinition() = this.reachingDefinition(pred) or result.getDefinition() = this.inputEdgeRefinement(pred) } /** Gets an input variable for this phi node. */ - EssaVariable getAnInput() { - result = this.getInput(_) - } + EssaVariable getAnInput() { result = this.getInput(_) } /** Holds if forall incoming edges in the flow graph, there is an input variable */ predicate isComplete() { - forall(BasicBlock pred | - pred = this.getBasicBlock().getAPredecessor() | + forall(BasicBlock pred | pred = this.getBasicBlock().getAPredecessor() | exists(this.getInput(pred)) ) } - override string toString() { - result = "SSA Phi Function" - } + override string toString() { result = "SSA Phi Function" } /** Gets the basic block that succeeds this phi node. */ - override BasicBlock getBasicBlock() { - this = TPhiFunction(_, result) - } + override BasicBlock getBasicBlock() { this = TPhiFunction(_, result) } - override Location getLocation() { - result = this.getBasicBlock().getNode(0).getLocation() - } + override Location getLocation() { result = this.getBasicBlock().getNode(0).getLocation() } /** Helper for `argList(n)`. */ private int rankInput(EssaVariable input) { @@ -330,12 +286,10 @@ class PhiFunction extends EssaDefinition, TPhiFunction { /** Helper for `argList()`. */ private string argList(int n) { - exists(EssaVariable input | - n = this.rankInput(input) - | + exists(EssaVariable input | n = this.rankInput(input) | n = 1 and result = input.getRepresentation() or - n > 1 and result = this.argList(n-1) + ", " + input.getRepresentation() + n > 1 and result = this.argList(n - 1) + ", " + input.getRepresentation() ) } @@ -352,13 +306,12 @@ class PhiFunction extends EssaDefinition, TPhiFunction { or result = "phi(" + this.argList() + ")" or - exists(this.getAnInput()) and not exists(this.argList()) and + exists(this.getAnInput()) and + not exists(this.argList()) and result = "phi(" + this.getSourceVariable().getName() + "??)" } - override Scope getScope() { - result = this.getBasicBlock().getScope() - } + override Scope getScope() { result = this.getBasicBlock().getScope() } private EssaEdgeRefinement piInputDefinition(EssaVariable input) { input = this.getAnInput() and @@ -367,7 +320,8 @@ class PhiFunction extends EssaDefinition, TPhiFunction { input = this.getAnInput() and result = input.getDefinition().(PhiFunction).piInputDefinition(_) } - /** Gets the variable which is the common and complete input to all pi-nodes that are themselves + /** + * Gets the variable which is the common and complete input to all pi-nodes that are themselves * inputs to this phi-node. * For example: * ``` @@ -387,19 +341,15 @@ class PhiFunction extends EssaDefinition, TPhiFunction { * meaning that we cannot track `x` from `x0` to `x3`. * By using `getShortCircuitInput()` we can do so, since the short-circuit input of `x3` is `x0`. */ - pragma [noinline] + pragma[noinline] EssaVariable getShortCircuitInput() { exists(BasicBlock common | - forall(EssaVariable input | - input = this.getAnInput() | + forall(EssaVariable input | input = this.getAnInput() | common = this.piInputDefinition(input).getPredecessor() - ) - and - forall(BasicBlock succ | - succ = common.getASuccessor() | + ) and + forall(BasicBlock succ | succ = common.getASuccessor() | succ = this.piInputDefinition(_).getSuccessor() - ) - and + ) and exists(EssaEdgeRefinement ref | ref = this.piInputDefinition(_) and ref.getPredecessor() = common and @@ -409,14 +359,12 @@ class PhiFunction extends EssaDefinition, TPhiFunction { } } -/** A definition of an ESSA variable that is not directly linked to +/** + * A definition of an ESSA variable that is not directly linked to * another ESSA variable. */ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { - - override string toString() { - result = "Essa node definition" - } + override string toString() { result = "Essa node definition" } override ControlFlowNode getAUse() { exists(SsaSourceVariable v, BasicBlock b, int i | @@ -432,22 +380,14 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { ) } - override SsaSourceVariable getSourceVariable() { - this = TEssaNodeDefinition(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaNodeDefinition(result, _, _) } /** Gets the ControlFlowNode corresponding to this definition */ - ControlFlowNode getDefiningNode() { - this.definedBy(_, result) - } + ControlFlowNode getDefiningNode() { this.definedBy(_, result) } - override Location getLocation() { - result = this.getDefiningNode().getLocation() - } + override Location getLocation() { result = this.getDefiningNode().getLocation() } - override string getRepresentation() { - result = this.getAQlClass() - } + override string getRepresentation() { result = this.getAQlClass() } override Scope getScope() { exists(BasicBlock defb | @@ -457,26 +397,19 @@ class EssaNodeDefinition extends EssaDefinition, TEssaNodeDefinition { } predicate definedBy(SsaSourceVariable v, ControlFlowNode def) { - exists(BasicBlock b, int i | - def = b.getNode(i) | - this = TEssaNodeDefinition(v, b, i+i) + exists(BasicBlock b, int i | def = b.getNode(i) | + this = TEssaNodeDefinition(v, b, i + i) or - this = TEssaNodeDefinition(v, b, i+i+1) + this = TEssaNodeDefinition(v, b, i + i + 1) ) } - override BasicBlock getBasicBlock(){ - result = this.getDefiningNode().getBasicBlock() - } - + override BasicBlock getBasicBlock() { result = this.getDefiningNode().getBasicBlock() } } /** A definition of an ESSA variable that takes another ESSA variable as an input. */ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { - - override string toString() { - result = "SSA filter definition" - } + override string toString() { result = "SSA filter definition" } /** Gets the SSA variable to which this refinement applies. */ EssaVariable getInput() { @@ -498,18 +431,12 @@ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { ) } - override SsaSourceVariable getSourceVariable() { - this = TEssaNodeRefinement(result, _, _) - } + override SsaSourceVariable getSourceVariable() { this = TEssaNodeRefinement(result, _, _) } /** Gets the ControlFlowNode corresponding to this definition */ - ControlFlowNode getDefiningNode() { - this.definedBy(_, result) - } + ControlFlowNode getDefiningNode() { this.definedBy(_, result) } - override Location getLocation() { - result = this.getDefiningNode().getLocation() - } + override Location getLocation() { result = this.getDefiningNode().getLocation() } override string getRepresentation() { result = this.getAQlClass() + "(" + this.getInput().getRepresentation() + ")" @@ -526,23 +453,19 @@ class EssaNodeRefinement extends EssaDefinition, TEssaNodeRefinement { } predicate definedBy(SsaSourceVariable v, ControlFlowNode def) { - exists(BasicBlock b, int i | - def = b.getNode(i) | - this = TEssaNodeRefinement(v, b, i+i) + exists(BasicBlock b, int i | def = b.getNode(i) | + this = TEssaNodeRefinement(v, b, i + i) or - this = TEssaNodeRefinement(v, b, i+i+1) + this = TEssaNodeRefinement(v, b, i + i + 1) ) } - override BasicBlock getBasicBlock(){ - result = this.getDefiningNode().getBasicBlock() - } - + override BasicBlock getBasicBlock() { result = this.getDefiningNode().getBasicBlock() } } pragma[noopt] private EssaVariable potential_input(EssaNodeRefinement ref) { - exists(ControlFlowNode use, SsaSourceVariable var, ControlFlowNode def | + exists(ControlFlowNode use, SsaSourceVariable var, ControlFlowNode def | var.hasRefinement(use, def) and use = result.getAUse() and var = result.getSourceVariable() and @@ -559,7 +482,6 @@ deprecated class PyNodeRefinement = EssaNodeRefinement; /** An assignment to a variable `v = val` */ class AssignmentDefinition extends EssaNodeDefinition { - AssignmentDefinition() { SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _) } @@ -568,15 +490,11 @@ class AssignmentDefinition extends EssaNodeDefinition { SsaSource::assignment_definition(this.getSourceVariable(), this.getDefiningNode(), result) } - override string getRepresentation() { - result = this.getValue().getNode().toString() - } - + override string getRepresentation() { result = this.getValue().getNode().toString() } } /** Capture of a raised exception `except ExceptionType ex:` */ -class ExceptionCapture extends EssaNodeDefinition { - +class ExceptionCapture extends EssaNodeDefinition { ExceptionCapture() { SsaSource::exception_capture(this.getSourceVariable(), this.getDefiningNode()) } @@ -588,15 +506,11 @@ class ExceptionCapture extends EssaNodeDefinition { ) } - override string getRepresentation() { - result = "except " + this.getSourceVariable().getName() - } - + override string getRepresentation() { result = "except " + this.getSourceVariable().getName() } } /** An assignment to a variable as part of a multiple assignment `..., v, ... = val` */ class MultiAssignmentDefinition extends EssaNodeDefinition { - MultiAssignmentDefinition() { SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), _, _) } @@ -610,130 +524,99 @@ class MultiAssignmentDefinition extends EssaNodeDefinition { /** Holds if `this` has (zero-based) index `index` in `lhs`. */ predicate indexOf(int index, SequenceNode lhs) { - SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, lhs) + SsaSource::multi_assignment_definition(this.getSourceVariable(), this.getDefiningNode(), index, + lhs) } - - } /** A definition of a variable in a `with` statement */ class WithDefinition extends EssaNodeDefinition { + WithDefinition() { SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode()) } - WithDefinition () { - SsaSource::with_definition(this.getSourceVariable(), this.getDefiningNode()) - } - - override string getRepresentation() { - result = "with" - } - + override string getRepresentation() { result = "with" } } /** A definition of a variable by declaring it as a parameter */ class ParameterDefinition extends EssaNodeDefinition { - ParameterDefinition() { SsaSource::parameter_definition(this.getSourceVariable(), this.getDefiningNode()) } - predicate isSelf() { - this.getDefiningNode().getNode().(Parameter).isSelf() - } + predicate isSelf() { this.getDefiningNode().getNode().(Parameter).isSelf() } /** Gets the control flow node for the default value of this parameter */ - ControlFlowNode getDefault() { - result.getNode() = this.getParameter().getDefault() - } + ControlFlowNode getDefault() { result.getNode() = this.getParameter().getDefault() } /** Gets the annotation control flow node of this parameter */ - ControlFlowNode getAnnotation() { - result.getNode() = this.getParameter().getAnnotation() - } + ControlFlowNode getAnnotation() { result.getNode() = this.getParameter().getAnnotation() } /** Gets the name of this parameter definition */ - string getName() { - result = this.getParameter().asName().getId() - } + string getName() { result = this.getParameter().asName().getId() } predicate isVarargs() { exists(Function func | func.getVararg() = this.getDefiningNode().getNode()) } - /** Holds if this parameter is a 'kwargs' parameter. + /** + * Holds if this parameter is a 'kwargs' parameter. * The `kwargs` in `f(a, b, **kwargs)`. */ predicate isKwargs() { exists(Function func | func.getKwarg() = this.getDefiningNode().getNode()) } - Parameter getParameter() { - result = this.getDefiningNode().getNode() - } - + Parameter getParameter() { result = this.getDefiningNode().getNode() } } - /** A deletion of a variable `del v` */ class DeletionDefinition extends EssaNodeDefinition { - DeletionDefinition() { SsaSource::deletion_definition(this.getSourceVariable(), this.getDefiningNode()) } - } -/** Definition of variable at the entry of a scope. Usually this represents the transfer of +/** + * Definition of variable at the entry of a scope. Usually this represents the transfer of * a global or non-local variable from one scope to another. */ class ScopeEntryDefinition extends EssaNodeDefinition { - ScopeEntryDefinition() { this.getDefiningNode() = this.getSourceVariable().getScopeEntryDefinition() and not this instanceof ImplicitSubModuleDefinition } - override Scope getScope() { - result.getEntryNode() = this.getDefiningNode() - } - + override Scope getScope() { result.getEntryNode() = this.getDefiningNode() } } /** Possible redefinition of variable via `from ... import *` */ class ImportStarRefinement extends EssaNodeRefinement { - ImportStarRefinement() { SsaSource::import_star_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - } /** Assignment of an attribute `obj.attr = val` */ class AttributeAssignment extends EssaNodeRefinement { - AttributeAssignment() { SsaSource::attribute_assignment_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - string getName() { - result = this.getDefiningNode().(AttrNode).getName() - } + string getName() { result = this.getDefiningNode().(AttrNode).getName() } - ControlFlowNode getValue() { - result = this.getDefiningNode().(DefinitionNode).getValue() - } + ControlFlowNode getValue() { result = this.getDefiningNode().(DefinitionNode).getValue() } override string getRepresentation() { - result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")" + result = + this.getAQlClass() + " '" + this.getName() + "'(" + this.getInput().getRepresentation() + ")" or not exists(this.getInput()) and - result = this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)" + result = + this.getAQlClass() + " '" + this.getName() + "'(" + this.getSourceVariable().getName() + "??)" } - } /** A use of a variable as an argument, `foo(v)`, which might modify the object referred to. */ class ArgumentRefinement extends EssaNodeRefinement { - ControlFlowNode argument; ArgumentRefinement() { @@ -747,20 +630,15 @@ class ArgumentRefinement extends EssaNodeRefinement { /** Deletion of an attribute `del obj.attr`. */ class EssaAttributeDeletion extends EssaNodeRefinement { - EssaAttributeDeletion() { SsaSource::attribute_deletion_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } - string getName() { - result = this.getDefiningNode().(AttrNode).getName() - } - + string getName() { result = this.getDefiningNode().(AttrNode).getName() } } /** A pi-node (guard) with only one successor. */ class SingleSuccessorGuard extends EssaNodeRefinement { - SingleSuccessorGuard() { SsaSource::test_refinement(this.getSourceVariable(), _, this.getDefiningNode()) } @@ -778,35 +656,28 @@ class SingleSuccessorGuard extends EssaNodeRefinement { result = EssaNodeRefinement.super.getRepresentation() + " [??]" } - ControlFlowNode getTest() { - result = this.getDefiningNode() - } + ControlFlowNode getTest() { result = this.getDefiningNode() } predicate useAndTest(ControlFlowNode use, ControlFlowNode test) { test = this.getDefiningNode() and SsaSource::test_refinement(this.getSourceVariable(), use, test) } - } -/** Implicit definition of the names of sub-modules in a package. +/** + * Implicit definition of the names of sub-modules in a package. * Although the interpreter does not pre-define these names, merely populating them * as they are imported, this is a good approximation for static analysis. */ class ImplicitSubModuleDefinition extends EssaNodeDefinition { - ImplicitSubModuleDefinition() { SsaSource::init_module_submodule_defn(this.getSourceVariable(), this.getDefiningNode()) } - } /** An implicit (possible) definition of an escaping variable at a call-site */ class CallsiteRefinement extends EssaNodeRefinement { - - override string toString() { - result = "CallsiteRefinement" - } + override string toString() { result = "CallsiteRefinement" } CallsiteRefinement() { exists(SsaSourceVariable var, ControlFlowNode defn | @@ -818,49 +689,37 @@ class CallsiteRefinement extends EssaNodeRefinement { ) } - CallNode getCall() { - this.getDefiningNode() = result - } - + CallNode getCall() { this.getDefiningNode() = result } } /** An implicit (possible) modification of the object referred at a method call */ class MethodCallsiteRefinement extends EssaNodeRefinement { - MethodCallsiteRefinement() { - SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode()) - and not this instanceof SingleSuccessorGuard - } - - CallNode getCall() { - this.getDefiningNode() = result + SsaSource::method_call_refinement(this.getSourceVariable(), _, this.getDefiningNode()) and + not this instanceof SingleSuccessorGuard } + CallNode getCall() { this.getDefiningNode() = result } } /** An implicit (possible) modification of `self` at a method call */ class SelfCallsiteRefinement extends MethodCallsiteRefinement { - - SelfCallsiteRefinement() { - this.getSourceVariable().(Variable).isSelf() - } - + SelfCallsiteRefinement() { this.getSourceVariable().(Variable).isSelf() } } /** Python specific sub-class of generic EssaEdgeRefinement */ class PyEdgeRefinement extends EssaEdgeRefinement { - override string getRepresentation() { - /* This is for testing so use capital 'P' to make it sort before 'phi' and - * be more visually distinctive. */ + /* + * This is for testing so use capital 'P' to make it sort before 'phi' and + * be more visually distinctive. + */ + result = "Pi(" + this.getInput().getRepresentation() + ") [" + this.getSense() + "]" or not exists(this.getInput()) and result = "Pi(" + this.getSourceVariable().getName() + "??) [" + this.getSense() + "]" } - ControlFlowNode getTest() { - result = this.getPredecessor().getLastNode() - } - + ControlFlowNode getTest() { result = this.getPredecessor().getLastNode() } } diff --git a/python/ql/src/semmle/python/essa/SsaCompute.qll b/python/ql/src/semmle/python/essa/SsaCompute.qll index cd359a0edf3..5a0980ed973 100644 --- a/python/ql/src/semmle/python/essa/SsaCompute.qll +++ b/python/ql/src/semmle/python/essa/SsaCompute.qll @@ -1,28 +1,29 @@ -/** Provides predicates for computing Enhanced SSA form +/** + * Provides predicates for computing Enhanced SSA form * Computation of ESSA form is identical to plain SSA form, * but what counts as a use of definition differs. - * + * * ## Language independent data-flow graph construction - * + * * Construction of the data-flow graph is based on the principles behind SSA variables. - * + * * The definition of an SSA variable is that (statically): - * + * * * Each variable has exactly one definition * * A variable's definition dominates all its uses. - * - * SSA form was originally designed for compiler use and thus a "definition" of an SSA variable is - * the same as a definition of the underlying source-code variable. For register allocation this is + * + * SSA form was originally designed for compiler use and thus a "definition" of an SSA variable is + * the same as a definition of the underlying source-code variable. For register allocation this is * sufficient to treat the variable as equivalent to the value held in the variable. - * + * * However, this doesn't always work the way we want it for data-flow analysis. - * - * When we start to consider attribute assignment, tests on the value referred to be a variable, + * + * When we start to consider attribute assignment, tests on the value referred to be a variable, * escaping variables, implicit definitions, etc., we need something finer grained. - * + * * A data-flow variable has the same properties as a normal SSA variable, but it also has the property that * *anything* that may change the way we view an object referred to by a variable should be treated as a definition of that variable. - * + * * For example, tests are treated as definitions, so for the following Python code: * ```python * x = None @@ -39,7 +40,7 @@ * from which is it possible to infer that `x3` may not be None. * [ Phi functions are standard SSA, a Pi function is a filter or guard on the possible values that a variable * may hold] - * + * * Attribute assignments are also treated as definitions, so for the following Python code: * ```python * x = C() @@ -55,13 +56,13 @@ * y1 = attr-assign(y0, .b = 1) * ``` * From which we can infer that `x1.a` is `1` but we know nothing about `y0.a` despite it being the same type. - * + * * We can also insert "definitions" for transfers of values (say in global variables) where we do not yet know the call-graph. For example, * ```python * def foo(): * global g * g = 1 - * + * * def bar(): * foo() * g @@ -72,7 +73,7 @@ * def foo(): * g0 = scope-entry(g) * g1 = 1 - * + * * def bar(): * g2 = scope-entry(g) * foo() @@ -86,57 +87,63 @@ * g3 = g1 * ``` * and thus it falls out that `g3` must be `1`. - * */ - import python - -private cached module SsaComputeImpl { - - cached module EssaDefinitionsImpl { - +cached +private module SsaComputeImpl { + cached + module EssaDefinitionsImpl { /** Whether `n` is a live update that is a definition of the variable `v`. */ - cached predicate variableDefinition(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableDefinition( + SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i + ) { SsaComputeImpl::variableDefine(v, n, b, i) and SsaComputeImpl::defUseRank(v, b, rankix, i) and - ( - SsaComputeImpl::defUseRank(v, b, rankix+1, _) and not SsaComputeImpl::defRank(v, b, rankix+1, _) + ( + SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and + not SsaComputeImpl::defRank(v, b, rankix + 1, _) or - not SsaComputeImpl::defUseRank(v, b, rankix+1, _) and Liveness::liveAtExit(v, b) + not SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and Liveness::liveAtExit(v, b) ) } /** Whether `n` is a live update that is a definition of the variable `v`. */ - cached predicate variableRefinement(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableRefinement( + SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i + ) { SsaComputeImpl::variableRefine(v, n, b, i) and SsaComputeImpl::defUseRank(v, b, rankix, i) and - ( - SsaComputeImpl::defUseRank(v, b, rankix+1, _) and not SsaComputeImpl::defRank(v, b, rankix+1, _) + ( + SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and + not SsaComputeImpl::defRank(v, b, rankix + 1, _) or - not SsaComputeImpl::defUseRank(v, b, rankix+1, _) and Liveness::liveAtExit(v, b) + not SsaComputeImpl::defUseRank(v, b, rankix + 1, _) and Liveness::liveAtExit(v, b) ) } - cached predicate variableUpdate(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { + cached + predicate variableUpdate(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int rankix, int i) { variableDefinition(v, n, b, rankix, i) or variableRefinement(v, n, b, rankix, i) } /** Holds if `def` is a pi-node for `v` on the edge `pred` -> `succ` */ - cached predicate piNode(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { + cached + predicate piNode(SsaSourceVariable v, BasicBlock pred, BasicBlock succ) { v.hasRefinementEdge(_, pred, succ) and Liveness::liveAtEntry(v, succ) } - /** A phi node for `v` at the beginning of basic block `b`. */ - cached predicate phiNode(SsaSourceVariable v, BasicBlock b) { + /** A phi node for `v` at the beginning of basic block `b`. */ + cached + predicate phiNode(SsaSourceVariable v, BasicBlock b) { ( - exists(BasicBlock def | def.dominanceFrontier(b) | - SsaComputeImpl::ssaDef(v, def) - ) + exists(BasicBlock def | def.dominanceFrontier(b) | SsaComputeImpl::ssaDef(v, def)) or piNode(v, _, b) and strictcount(b.getAPredecessor()) > 1 ) and @@ -144,25 +151,26 @@ private cached module SsaComputeImpl { } } - cached predicate variableDefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { - v.hasDefiningNode(n) - and + cached + predicate variableDefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + v.hasDefiningNode(n) and exists(int j | n = b.getNode(j) and - i = j*2 + 1 + i = j * 2 + 1 ) } - cached predicate variableRefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { - v.hasRefinement(_, n) - and + cached + predicate variableRefine(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + v.hasRefinement(_, n) and exists(int j | n = b.getNode(j) and - i = j*2 + 1 + i = j * 2 + 1 ) } - cached predicate variableDef(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { + cached + predicate variableDef(SsaSourceVariable v, ControlFlowNode n, BasicBlock b, int i) { variableDefine(v, n, b, i) or variableRefine(v, n, b, i) } @@ -174,22 +182,25 @@ private cached module SsaComputeImpl { * irrelevant indices at which there is no definition or use when traversing * basic blocks. */ - cached predicate defUseRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { - i = rank[rankix](int j | variableDef(v, _, b, j) or variableUse(v, _, b, j)) + cached + predicate defUseRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { + i = rank[rankix](int j | variableDef(v, _, b, j) or variableUse(v, _, b, j)) } /** A definition of a variable occurring at the specified rank index in basic block `b`. */ - cached predicate defRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { - variableDef(v, _, b, i) and - defUseRank(v, b, rankix, i) + cached + predicate defRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { + variableDef(v, _, b, i) and + defUseRank(v, b, rankix, i) } /** A `VarAccess` `use` of `v` in `b` at index `i`. */ - cached predicate variableUse(SsaSourceVariable v, ControlFlowNode use, BasicBlock b, int i) { + cached + predicate variableUse(SsaSourceVariable v, ControlFlowNode use, BasicBlock b, int i) { (v.getAUse() = use or v.hasRefinement(use, _)) and exists(int j | - b.getNode(j) = use and - i = 2*j + b.getNode(j) = use and + i = 2 * j ) } @@ -197,7 +208,8 @@ private cached module SsaComputeImpl { * A definition of an SSA variable occurring at the specified position. * This is either a phi node, a `VariableUpdate`, or a parameter. */ - cached predicate ssaDef(SsaSourceVariable v, BasicBlock b) { + cached + predicate ssaDef(SsaSourceVariable v, BasicBlock b) { EssaDefinitions::phiNode(v, b) or EssaDefinitions::variableUpdate(v, _, b, _, _) @@ -216,10 +228,13 @@ private cached module SsaComputeImpl { */ /** The maximum rank index for the given variable and basic block. */ - cached int lastRank(SsaSourceVariable v, BasicBlock b) { + cached + int lastRank(SsaSourceVariable v, BasicBlock b) { result = max(int rankix | defUseRank(v, b, rankix, _)) or - not defUseRank(v, b, _, _) and (EssaDefinitions::phiNode(v, b) or EssaDefinitions::piNode(v, _, b)) and result = 0 + not defUseRank(v, b, _, _) and + (EssaDefinitions::phiNode(v, b) or EssaDefinitions::piNode(v, _, b)) and + result = 0 } private predicate ssaDefRank(SsaSourceVariable v, BasicBlock b, int rankix, int i) { @@ -227,22 +242,35 @@ private cached module SsaComputeImpl { or EssaDefinitions::phiNode(v, b) and rankix = 0 and i = phiIndex() or - EssaDefinitions::piNode(v, _, b) and EssaDefinitions::phiNode(v, b) and rankix = -1 and i = piIndex() + EssaDefinitions::piNode(v, _, b) and + EssaDefinitions::phiNode(v, b) and + rankix = -1 and + i = piIndex() or - EssaDefinitions::piNode(v, _, b) and not EssaDefinitions::phiNode(v, b) and rankix = 0 and i = piIndex() + EssaDefinitions::piNode(v, _, b) and + not EssaDefinitions::phiNode(v, b) and + rankix = 0 and + i = piIndex() } /** The SSA definition reaches the rank index `rankix` in its own basic block `b`. */ - cached predicate ssaDefReachesRank(SsaSourceVariable v, BasicBlock b, int i, int rankix) { - ssaDefRank(v, b, rankix, i) or - ssaDefReachesRank(v, b, i, rankix-1) and rankix <= lastRank(v, b) and not ssaDefRank(v, b, rankix, _) + cached + predicate ssaDefReachesRank(SsaSourceVariable v, BasicBlock b, int i, int rankix) { + ssaDefRank(v, b, rankix, i) + or + ssaDefReachesRank(v, b, i, rankix - 1) and + rankix <= lastRank(v, b) and + not ssaDefRank(v, b, rankix, _) } /** * The SSA definition of `v` at `def` reaches `use` in the same basic block * without crossing another SSA definition of `v`. */ - cached predicate ssaDefReachesUseWithinBlock(SsaSourceVariable v, BasicBlock b, int i, ControlFlowNode use) { + cached + predicate ssaDefReachesUseWithinBlock( + SsaSourceVariable v, BasicBlock b, int i, ControlFlowNode use + ) { exists(int rankix, int useix | ssaDefReachesRank(v, b, i, rankix) and defUseRank(v, b, rankix, useix) and @@ -250,41 +278,44 @@ private cached module SsaComputeImpl { ) } - cached module LivenessImpl { + cached + module LivenessImpl { + cached + predicate liveAtExit(SsaSourceVariable v, BasicBlock b) { liveAtEntry(v, b.getASuccessor()) } - cached predicate liveAtExit(SsaSourceVariable v, BasicBlock b) { - liveAtEntry(v, b.getASuccessor()) - } - - cached predicate liveAtEntry(SsaSourceVariable v, BasicBlock b) { + cached + predicate liveAtEntry(SsaSourceVariable v, BasicBlock b) { SsaComputeImpl::defUseRank(v, b, 1, _) and not SsaComputeImpl::defRank(v, b, 1, _) or not SsaComputeImpl::defUseRank(v, b, _, _) and liveAtExit(v, b) } - } - cached module SsaDefinitionsImpl { - - pragma [noinline] - private predicate reachesEndOfBlockRec(SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b) { + cached + module SsaDefinitionsImpl { + pragma[noinline] + private predicate reachesEndOfBlockRec( + SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b + ) { exists(BasicBlock idom | reachesEndOfBlock(v, defbb, defindex, idom) | idom = b.getImmediateDominator() ) } + /** * The SSA definition of `v` at `def` reaches the end of a basic block `b`, at * which point it is still live, without crossing another SSA definition of `v`. */ cached predicate reachesEndOfBlock(SsaSourceVariable v, BasicBlock defbb, int defindex, BasicBlock b) { - Liveness::liveAtExit(v, b) and - ( - defbb = b and SsaComputeImpl::ssaDefReachesRank(v, defbb, defindex, SsaComputeImpl::lastRank(v, b)) - or - // It is sufficient to traverse the dominator graph, cf. discussion above. - reachesEndOfBlockRec(v, defbb, defindex, b) and - not SsaComputeImpl::ssaDef(v, b) + Liveness::liveAtExit(v, b) and + ( + defbb = b and + SsaComputeImpl::ssaDefReachesRank(v, defbb, defindex, SsaComputeImpl::lastRank(v, b)) + or + // It is sufficient to traverse the dominator graph, cf. discussion above. + reachesEndOfBlockRec(v, defbb, defindex, b) and + not SsaComputeImpl::ssaDef(v, b) ) } @@ -294,15 +325,16 @@ private cached module SsaComputeImpl { */ cached predicate reachesUse(SsaSourceVariable v, BasicBlock defbb, int defindex, ControlFlowNode use) { - SsaComputeImpl::ssaDefReachesUseWithinBlock(v, defbb, defindex, use) or - exists(BasicBlock b | - SsaComputeImpl::variableUse(v, use, b, _) and - reachesEndOfBlock(v, defbb, defindex, b.getAPredecessor()) and - not SsaComputeImpl::ssaDefReachesUseWithinBlock(v, b, _, use) - ) + SsaComputeImpl::ssaDefReachesUseWithinBlock(v, defbb, defindex, use) + or + exists(BasicBlock b | + SsaComputeImpl::variableUse(v, use, b, _) and + reachesEndOfBlock(v, defbb, defindex, b.getAPredecessor()) and + not SsaComputeImpl::ssaDefReachesUseWithinBlock(v, b, _, use) + ) } - /*** + /** * Holds if `(defbb, defindex)` is an SSA definition of `v` that reaches an exit without crossing another * SSA definition of `v`. */ @@ -315,9 +347,7 @@ private cached module SsaComputeImpl { SsaComputeImpl::variableUse(v, use, last, index) ) } - } - } import SsaComputeImpl::SsaDefinitionsImpl as SsaDefinitions @@ -325,9 +355,8 @@ import SsaComputeImpl::EssaDefinitionsImpl as EssaDefinitions import SsaComputeImpl::LivenessImpl as Liveness /* This is exported primarily for testing */ - - -/* A note on numbering +/* + * A note on numbering * In order to create an SSA graph, we need an order of definitions and uses within a basic block. * To do this we index definitions and uses as follows: * Phi-functions have an index of -1, so precede all normal uses and definitions in a block. @@ -337,10 +366,8 @@ import SsaComputeImpl::LivenessImpl as Liveness * * a definition at the `j`th node of a block is given the index `2*j + 1`. */ -pragma [inline] +pragma[inline] int phiIndex() { result = -1 } -pragma [inline] +pragma[inline] int piIndex() { result = -2 } - - diff --git a/python/ql/src/semmle/python/essa/SsaDefinitions.qll b/python/ql/src/semmle/python/essa/SsaDefinitions.qll index 8a6bc274aa0..992a2bd96ac 100644 --- a/python/ql/src/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/src/semmle/python/essa/SsaDefinitions.qll @@ -1,44 +1,48 @@ -/** Provides classes and predicates for determining the uses and definitions of +/** + * Provides classes and predicates for determining the uses and definitions of * variables for ESSA form. */ import python private import semmle.python.pointsto.Base - - - -cached module SsaSource { - +cached +module SsaSource { /** Holds if `v` is used as the receiver in a method call. */ - cached predicate method_call_refinement(Variable v, ControlFlowNode use, CallNode call) { + cached + predicate method_call_refinement(Variable v, ControlFlowNode use, CallNode call) { use = v.getAUse() and call.getFunction().(AttrNode).getObject() = use and not test_contains(_, call) } /** Holds if `v` is defined by assignment at `defn` and given `value`. */ - cached predicate assignment_definition(Variable v, ControlFlowNode defn, ControlFlowNode value) { + cached + predicate assignment_definition(Variable v, ControlFlowNode defn, ControlFlowNode value) { defn.(NameNode).defines(v) and defn.(DefinitionNode).getValue() = value } /** Holds if `v` is defined by assignment of the captured exception. */ - cached predicate exception_capture(Variable v, NameNode defn) { + cached + predicate exception_capture(Variable v, NameNode defn) { defn.defines(v) and exists(ExceptFlowNode ex | ex.getName() = defn) } /** Holds if `v` is defined by a with statement. */ - cached predicate with_definition(Variable v, ControlFlowNode defn) { + cached + predicate with_definition(Variable v, ControlFlowNode defn) { exists(With with, Name var | with.getOptionalVars() = var and - var.getAFlowNode() = defn | + var.getAFlowNode() = defn + | var = v.getAStore() ) } /** Holds if `v` is defined by multiple assignment at `defn`. */ - cached predicate multi_assignment_definition(Variable v, ControlFlowNode defn, int n, SequenceNode lhs) { + cached + predicate multi_assignment_definition(Variable v, ControlFlowNode defn, int n, SequenceNode lhs) { ( defn.(NameNode).defines(v) or @@ -50,44 +54,52 @@ cached module SsaSource { } /** Holds if `v` is defined by a `for` statement, the definition being `defn` */ - cached predicate iteration_defined_variable(Variable v, ControlFlowNode defn, ControlFlowNode sequence) { + cached + predicate iteration_defined_variable(Variable v, ControlFlowNode defn, ControlFlowNode sequence) { exists(ForNode for | for.iterates(defn, sequence)) and defn.(NameNode).defines(v) } /** Holds if `v` is a parameter variable and `defn` is the CFG node for that parameter. */ - cached predicate parameter_definition(Variable v, ControlFlowNode defn) { + cached + predicate parameter_definition(Variable v, ControlFlowNode defn) { exists(Function f, Name param | f.getAnArg() = param or f.getVararg() = param or f.getKwarg() = param or - f.getKeywordOnlyArg(_) = param | + f.getKeywordOnlyArg(_) = param + | defn.getNode() = param and param.getVariable() = v ) } /** Holds if `v` is deleted at `del`. */ - cached predicate deletion_definition(Variable v, DeletionNode del) { + cached + predicate deletion_definition(Variable v, DeletionNode del) { del.getTarget().(NameNode).deletes(v) } - /** Holds if the name of `var` refers to a submodule of a package and `f` is the entry point + /** + * Holds if the name of `var` refers to a submodule of a package and `f` is the entry point * to the __init__ module of that package. */ - cached predicate init_module_submodule_defn(SsaSourceVariable var, ControlFlowNode f) { + cached + predicate init_module_submodule_defn(SsaSourceVariable var, ControlFlowNode f) { var instanceof GlobalVariable and exists(Module init | - init.isPackageInit() and exists(init.getPackage().getSubModule(var.getName())) and + init.isPackageInit() and + exists(init.getPackage().getSubModule(var.getName())) and init.getEntryNode() = f and var.getScope() = init ) } /** Holds if the `v` is in scope at a `from import ... *` and may thus be redefined by that statement */ - cached predicate import_star_refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { - use = def and def instanceof ImportStarNode - and + cached + predicate import_star_refinement(SsaSourceVariable v, ControlFlowNode use, ControlFlowNode def) { + use = def and + def instanceof ImportStarNode and ( v.getScope() = def.getScope() or @@ -99,13 +111,16 @@ cached module SsaSource { } /** Holds if an attribute is assigned at `def` and `use` is the use of `v` for that assignment */ - cached predicate attribute_assignment_refinement(Variable v, ControlFlowNode use, ControlFlowNode def) { + cached + predicate attribute_assignment_refinement(Variable v, ControlFlowNode use, ControlFlowNode def) { use.(NameNode).uses(v) and - def.isStore() and def.(AttrNode).getObject() = use + def.isStore() and + def.(AttrNode).getObject() = use } /** Holds if a `v` is used as an argument to `call`, which *may* modify the object referred to by `v` */ - cached predicate argument_refinement(Variable v, ControlFlowNode use, CallNode call) { + cached + predicate argument_refinement(Variable v, ControlFlowNode use, CallNode call) { use.(NameNode).uses(v) and call.getArg(0) = use and not method_call_refinement(v, _, call) and @@ -113,13 +128,15 @@ cached module SsaSource { } /** Holds if an attribute is deleted at `def` and `use` is the use of `v` for that deletion */ - cached predicate attribute_deletion_refinement(Variable v, NameNode use, DeletionNode def) { + cached + predicate attribute_deletion_refinement(Variable v, NameNode use, DeletionNode def) { use.uses(v) and def.getTarget().(AttrNode).getObject() = use } /** Holds if the set of possible values for `v` is refined by `test` and `use` is the use of `v` in that test. */ - cached predicate test_refinement(Variable v, ControlFlowNode use, ControlFlowNode test) { + cached + predicate test_refinement(Variable v, ControlFlowNode use, ControlFlowNode test) { use.(NameNode).uses(v) and test.getAChild*() = use and test.isBranch() and @@ -129,5 +146,4 @@ cached module SsaSource { not block.getLastNode() = test ) } - } diff --git a/python/ql/src/semmle/python/filters/GeneratedCode.qll b/python/ql/src/semmle/python/filters/GeneratedCode.qll index 18696239d63..5b1721945da 100644 --- a/python/ql/src/semmle/python/filters/GeneratedCode.qll +++ b/python/ql/src/semmle/python/filters/GeneratedCode.qll @@ -5,105 +5,118 @@ import semmle.python.templates.Templates * A file that is detected as being generated. */ abstract class GeneratedFile extends File { - abstract string getTool(); - } -/* We distinguish between a "lax" match which just includes "generated by" or similar versus a "strict" match which includes "this file is generated by" or similar +/* + * We distinguish between a "lax" match which just includes "generated by" or similar versus a "strict" match which includes "this file is generated by" or similar * "lax" matches are taken to indicate generated file if they occur at the top of a file. "strict" matches can occur anywhere. * There is no formal reason for the above, it just seems to work well in practice. */ library class GenericGeneratedFile extends GeneratedFile { - GenericGeneratedFile() { - not this instanceof SpecificGeneratedFile - and + not this instanceof SpecificGeneratedFile and ( - (lax_generated_by(this, _) or lax_generated_from(this, _)) and dont_modify(this) + (lax_generated_by(this, _) or lax_generated_from(this, _)) and + dont_modify(this) or - strict_generated_by(this, _) or strict_generated_from(this, _) + strict_generated_by(this, _) + or + strict_generated_from(this, _) or auto_generated(this) ) } - override string getTool() { - lax_generated_by(this, result) or strict_generated_by(this, result) - } - + override string getTool() { lax_generated_by(this, result) or strict_generated_by(this, result) } } private string comment_or_docstring(File f, boolean before_code) { - exists(Comment c | + exists(Comment c | c.getLocation().getFile() = f and - result = c.getText() | - if exists(Stmt s | s.getEnclosingModule().getFile() = f and s.getLocation().getStartLine() < c.getLocation().getStartLine()) then - before_code = false - else - before_code = true + result = c.getText() + | + if + exists(Stmt s | + s.getEnclosingModule().getFile() = f and + s.getLocation().getStartLine() < c.getLocation().getStartLine() + ) + then before_code = false + else before_code = true ) or exists(Module m | m.getFile() = f | result = m.getDocString().getText() and before_code = true ) - } private predicate lax_generated_by(File f, string tool) { exists(string comment | comment = comment_or_docstring(f, _) | - tool = comment.regexpCapture("(?is).*\\b(?:(?:auto[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", 1) + tool = + comment + .regexpCapture("(?is).*\\b(?:(?:auto[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate lax_generated_from(File f, string src) { - exists(string comment | comment = comment_or_docstring(f, _) | - src = comment.regexpCapture("(?is).*\\b((?:auto[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", 1) - ) + exists(string comment | comment = comment_or_docstring(f, _) | + src = + comment + .regexpCapture("(?is).*\\b((?:auto[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", + 1) + ) } private predicate strict_generated_by(File f, string tool) { exists(string comment | comment = comment_or_docstring(f, true) | - tool = comment.regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", 1) + tool = + comment + .regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) by (?:the )?([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate strict_generated_from(File f, string src) { exists(string comment | comment = comment_or_docstring(f, true) | - src = comment.regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", 1) + src = + comment + .regexpCapture("(?is)# *(?:this +)?(?:(?:code|file) +)?(?:is +)?(?:(?:auto(?:matically)?[ -]?)?generated|created automatically) from ([-/\\w.]+[-/\\w]).*", + 1) ) } private predicate dont_modify(File f) { - comment_or_docstring(f, _).regexpMatch("(?is).*\\b(Do not|Don't) (edit|modify|make changes)\\b.*") + comment_or_docstring(f, _).regexpMatch("(?is).*\\b(Do not|Don't) (edit|modify|make changes)\\b.*") } private predicate auto_generated(File f) { exists(Comment c | c.getLocation().getFile() = f and - c.getText().regexpMatch("(?is)# *this +(code|file) +is +(auto(matically)?[ -]?generated|created automatically).*") + c + .getText() + .regexpMatch("(?is)# *this +(code|file) +is +(auto(matically)?[ -]?generated|created automatically).*") ) } - /** - * A file generated by a template engine + * A file generated by a template engine */ abstract library class SpecificGeneratedFile extends GeneratedFile { - /* Currently cover Spitfire, Pyxl and Mako. + /* + * Currently cover Spitfire, Pyxl and Mako. * Django templates are not compiled to Python. * Jinja2 templates are compiled direct to bytecode via the ast. */ -} + + } /** File generated by the spitfire templating engine */ class SpitfireGeneratedFile extends SpecificGeneratedFile { - SpitfireGeneratedFile() { - exists(Module m | - m.getFile() = this and not m instanceof SpitfireTemplate | + exists(Module m | m.getFile() = this and not m instanceof SpitfireTemplate | exists(ImportMember template_method, ImportExpr spitfire_runtime_template | spitfire_runtime_template.getName() = "spitfire.runtime.template" and template_method.getModule() = spitfire_runtime_template and @@ -112,28 +125,18 @@ class SpitfireGeneratedFile extends SpecificGeneratedFile { ) } - override string getTool() { - result = "spitfire" - } - + override string getTool() { result = "spitfire" } } /** File generated by the pyxl templating engine */ class PyxlGeneratedFile extends SpecificGeneratedFile { + PyxlGeneratedFile() { this.getSpecifiedEncoding() = "pyxl" } - PyxlGeneratedFile() { - this.getSpecifiedEncoding() = "pyxl" - } - - override string getTool() { - result = "pyxl" - } - + override string getTool() { result = "pyxl" } } /** File generated by the mako templating engine */ class MakoGeneratedFile extends SpecificGeneratedFile { - MakoGeneratedFile() { exists(Module m | m.getFile() = this | from_mako_import(m) = "runtime" and @@ -147,38 +150,31 @@ class MakoGeneratedFile extends SpecificGeneratedFile { ) and exists(Assign a, Name n | a.getScope() = m and a.getATarget() = n and n.getId() = "_magic_number" - ) + ) ) } - override string getTool() { - result = "mako" - } - + override string getTool() { result = "mako" } } string from_mako_import(Module m) { exists(ImportMember member, ImportExpr mako | member.getScope() = m and member.getModule() = mako and - mako.getName() = "mako" | - result = member.getName() + mako.getName() = "mako" + | + result = member.getName() ) } /** File generated by Google's protobuf tool. */ class ProtobufGeneratedFile extends SpecificGeneratedFile { - ProtobufGeneratedFile() { - this.getName().regexpMatch(".*_pb2?.py") - and - exists(Module m | - m.getFile() = this | - exists(ImportExpr imp | - imp.getEnclosingModule() = m | + this.getAbsolutePath().regexpMatch(".*_pb2?.py") and + exists(Module m | m.getFile() = this | + exists(ImportExpr imp | imp.getEnclosingModule() = m | imp.getImportedModuleName() = "google.net.proto2.python.public" - ) - and + ) and exists(AssignStmt a, Name n | a.getEnclosingModule() = m and a.getATarget() = n and @@ -187,8 +183,5 @@ class ProtobufGeneratedFile extends SpecificGeneratedFile { ) } - override string getTool() { - result = "protobuf" - } - + override string getTool() { result = "protobuf" } } diff --git a/python/ql/src/semmle/python/filters/Tests.qll b/python/ql/src/semmle/python/filters/Tests.qll index 6c42fec61ab..7b9c2fa38cd 100644 --- a/python/ql/src/semmle/python/filters/Tests.qll +++ b/python/ql/src/semmle/python/filters/Tests.qll @@ -1,12 +1,11 @@ import python -abstract class TestScope extends Scope {} +abstract class TestScope extends Scope { } // don't extend Class directly to avoid ambiguous method warnings class UnitTestClass extends TestScope { UnitTestClass() { - exists(ClassObject c | - this = c.getPyClass() | + exists(ClassObject c | this = c.getPyClass() | c.getASuperType() = theUnitTestPackage().attr(_) or c.getASuperType().getName().toLowerCase() = "testcase" @@ -14,35 +13,27 @@ class UnitTestClass extends TestScope { } } -PackageObject theUnitTestPackage() { - result.getName() = "unittest" -} +PackageObject theUnitTestPackage() { result.getName() = "unittest" } -abstract class Test extends TestScope {} +abstract class Test extends TestScope { } class UnitTestFunction extends Test { - UnitTestFunction() { - this.getScope+() instanceof UnitTestClass - and + this.getScope+() instanceof UnitTestClass and this.(Function).getName().matches("test%") } } class PyTestFunction extends Test { - PyTestFunction() { exists(Module pytest | pytest.getName() = "pytest") and this.(Function).getName().matches("test%") } - } class NoseTestFunction extends Test { - NoseTestFunction() { exists(Module nose | nose.getName() = "nose") and this.(Function).getName().matches("test%") } - } diff --git a/python/ql/src/semmle/python/libraries/Zope.qll b/python/ql/src/semmle/python/libraries/Zope.qll index 8f69c792b5d..381e40edeab 100644 --- a/python/ql/src/semmle/python/libraries/Zope.qll +++ b/python/ql/src/semmle/python/libraries/Zope.qll @@ -1,12 +1,10 @@ /** Utilities for handling the zope libraries */ import python - private import semmle.python.pointsto.PointsTo /** A method that to a sub-class of `zope.interface.Interface` */ deprecated class ZopeInterfaceMethod extends PyFunctionObject { - /** Holds if this method belongs to a class that sub-classes `zope.interface.Interface` */ ZopeInterfaceMethod() { exists(Object interface, ClassObject owner | @@ -16,22 +14,17 @@ deprecated class ZopeInterfaceMethod extends PyFunctionObject { ) } - override int minParameters() { - result = super.minParameters() + 1 - } + override int minParameters() { result = super.minParameters() + 1 } override int maxParameters() { - if exists(this.getFunction().getVararg()) then - result = super.maxParameters() - else - result = super.maxParameters() + 1 + if exists(this.getFunction().getVararg()) + then result = super.maxParameters() + else result = super.maxParameters() + 1 } - } /** A method that belongs to a sub-class of `zope.interface.Interface` */ class ZopeInterfaceMethodValue extends PythonFunctionValue { - /** Holds if this method belongs to a class that sub-classes `zope.interface.Interface` */ ZopeInterfaceMethodValue() { exists(Value interface, ClassValue owner | @@ -44,15 +37,11 @@ class ZopeInterfaceMethodValue extends PythonFunctionValue { ) } - override int minParameters() { - result = super.minParameters() + 1 - } + override int minParameters() { result = super.minParameters() + 1 } override int maxParameters() { - if exists(this.getScope().getVararg()) then - result = super.maxParameters() - else - result = super.maxParameters() + 1 + if exists(this.getScope().getVararg()) + then result = super.maxParameters() + else result = super.maxParameters() + 1 } - } diff --git a/python/ql/src/semmle/python/objects/Callables.qll b/python/ql/src/semmle/python/objects/Callables.qll index 431d57bcfe7..b915e4bd5c2 100644 --- a/python/ql/src/semmle/python/objects/Callables.qll +++ b/python/ql/src/semmle/python/objects/Callables.qll @@ -1,6 +1,4 @@ - import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -8,9 +6,7 @@ private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins - abstract class CallableObjectInternal extends ObjectInternal { - /** Gets the scope of this callable if it has one */ abstract Function getScope(); @@ -26,7 +22,10 @@ abstract class CallableObjectInternal extends ObjectInternal { override ClassDecl getClassDeclaration() { none() } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } abstract NameNode getParameter(int n); @@ -36,11 +35,11 @@ abstract class CallableObjectInternal extends ObjectInternal { override int length() { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } @@ -50,12 +49,10 @@ abstract class CallableObjectInternal extends ObjectInternal { /* Callables aren't iterable */ override ObjectInternal getIterNext() { none() } - } /** Class representing Python functions */ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFunctionObject { - override Function getScope() { exists(CallableExpr expr | this = TPythonFunctionObject(expr.getAFlowNode()) and @@ -63,9 +60,7 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti ) } - override string toString() { - result = "Function " + this.getScope().getQualifiedName() - } + override string toString() { result = "Function " + this.getScope().getQualifiedName() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonFunctionObject(node) and context.appliesTo(node) @@ -77,19 +72,16 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti override predicate notTestableForEquality() { none() } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonFunctionObject(result) - } + override ControlFlowNode getOrigin() { this = TPythonFunctionObject(result) } - pragma [nomagic] + pragma[nomagic] override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { exists(Function func, ControlFlowNode rval, ControlFlowNode forigin | func = this.getScope() and - callee.appliesToScope(func) | + callee.appliesToScope(func) + | rval = func.getAReturnValueFlowNode() and PointsToInternal::pointsTo(rval, callee, obj, forigin) and origin = CfgOrigin::fromCfgNode(forigin) @@ -98,17 +90,20 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti procedureReturnsNone(callee, obj, origin) } - private predicate procedureReturnsNone(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + private predicate procedureReturnsNone( + PointsToContext callee, ObjectInternal obj, CfgOrigin origin + ) { exists(Function func | func = this.getScope() and - callee.appliesToScope(func) | + callee.appliesToScope(func) + | PointsToInternal::reachableBlock(blockReturningNone(func), callee) and obj = ObjectInternal::none_() and origin = CfgOrigin::unknown() ) } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { this.getScope().isProcedure() and obj = ObjectInternal::none_() and @@ -119,41 +114,37 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti scope = this.getScope() and paramOffset = 0 } - override string getName() { - result = this.getScope().getName() - } + override string getName() { result = this.getScope().getName() } override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::fromCfgNode(this.getOrigin()) + value = this and + origin = CfgOrigin::fromCfgNode(this.getOrigin()) } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { value = TBoundMethod(instance, this) and origin = CfgOrigin::unknown() } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) or - exists(BoundMethodObjectInternal bm | - bm.getACall(ctx) = result and this = bm.getFunction() - ) + exists(BoundMethodObjectInternal bm | bm.getACall(ctx) = result and this = bm.getFunction()) } - override NameNode getParameter(int n) { - result.getNode() = this.getScope().getArg(n) - } + override NameNode getParameter(int n) { result.getNode() = this.getScope().getArg(n) } override NameNode getParameterByName(string name) { result.getNode() = this.getScope().getArgByName(name) } - - override predicate neverReturns() { - InterProceduralPointsTo::neverReturns(this.getScope()) - } + override predicate neverReturns() { InterProceduralPointsTo::neverReturns(this.getScope()) } override predicate functionAndOffset(CallableObjectInternal function, int offset) { function = this and offset = 0 @@ -164,10 +155,8 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } - private BasicBlock blockReturningNone(Function func) { exists(Return ret | not exists(ret.getValue()) and @@ -176,38 +165,31 @@ private BasicBlock blockReturningNone(Function func) { ) } - /** Class representing built-in functions such as `len` or `print`. */ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunctionObject { + override Builtin getBuiltin() { this = TBuiltinFunctionObject(result) } - override Builtin getBuiltin() { - this = TBuiltinFunctionObject(result) - } + override string toString() { result = "Builtin-function " + this.getBuiltin().getName() } - override string toString() { - result = "Builtin-function " + this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } - - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } override predicate notTestableForEquality() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(Builtin func, BuiltinClassObjectInternal cls | func = this.getBuiltin() and func != Builtin::builtin("isinstance") and func != Builtin::builtin("issubclass") and func != Builtin::builtin("callable") and - cls = ObjectInternal::fromBuiltin(this.getReturnType()) | + cls = ObjectInternal::fromBuiltin(this.getReturnType()) + | obj = TUnknownInstance(cls) or cls = ObjectInternal::noneType() and obj = ObjectInternal::none_() @@ -221,17 +203,11 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } Builtin getReturnType() { exists(Builtin func | @@ -251,21 +227,25 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - none() - } + override NameNode getParameter(int n) { none() } - override NameNode getParameterByName(string name) { - none() - } + override NameNode getParameterByName(string name) { none() } override predicate neverReturns() { exists(ModuleObjectInternal sys | @@ -283,7 +263,6 @@ class BuiltinFunctionObjectInternal extends CallableObjectInternal, TBuiltinFunc override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } private Builtin getBuiltinFunctionReturnType(Builtin func) { @@ -297,7 +276,8 @@ private Builtin getBuiltinFunctionReturnType(Builtin func) { func = Builtin::builtin("__import__") and result = Builtin::special("ModuleType") or /* Fix a few minor inaccuracies in the CPython analysis */ - ext_rettype(func, result) and not ( + ext_rettype(func, result) and + not ( func = Builtin::builtin("__import__") or func = Builtin::builtin("compile") and result = Builtin::special("NoneType") @@ -309,34 +289,27 @@ private Builtin getBuiltinFunctionReturnType(Builtin func) { } /** Class representing methods of built-in classes (otherwise known as method-descriptors) such as `list.append`. */ - class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethodObject { + override Builtin getBuiltin() { this = TBuiltinMethodObject(result) } - override Builtin getBuiltin() { - this = TBuiltinMethodObject(result) - } + override string toString() { result = "builtin method " + this.getBuiltin().getName() } - override string toString() { - result = "builtin method " + this.getBuiltin().getName() - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - pragma [noinline] + pragma[noinline] override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(Builtin func, BuiltinClassObjectInternal cls | func = this.getBuiltin() and - cls = ObjectInternal::fromBuiltin(this.getReturnType()) | + cls = ObjectInternal::fromBuiltin(this.getReturnType()) + | obj = TUnknownInstance(cls) or cls = ObjectInternal::noneType() and obj = ObjectInternal::none_() @@ -352,41 +325,34 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod Builtin getReturnType() { /* If we have a record of the return type in our stubs, use that. */ - exists(Builtin func | - func = this.getBuiltin() | - ext_rettype(func, result) - ) + exists(Builtin func | func = this.getBuiltin() | ext_rettype(func, result)) } private predicate returnTypeUnknown() { - exists(Builtin func | - func = this.getBuiltin() | - not ext_rettype(func, _) - ) + exists(Builtin func | func = this.getBuiltin() | not ext_rettype(func, _)) } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } override Function getScope() { none() } override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::unknown() + value = this and + origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { value = TBoundMethod(instance, this) and origin = CfgOrigin::unknown() } @@ -394,13 +360,9 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - none() - } + override NameNode getParameter(int n) { none() } - override NameNode getParameterByName(string name) { - none() - } + override NameNode getParameterByName(string name) { none() } override predicate neverReturns() { none() } @@ -413,27 +375,20 @@ class BuiltinMethodObjectInternal extends CallableObjectInternal, TBuiltinMethod override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } -/** Class representing bound-methods. +/** + * Class representing bound-methods. * Note that built-in methods, such as `[].append` are also represented as bound-methods. * Although built-in methods and bound-methods are distinct classes in CPython, their behaviour * is the same and we treat them identically. */ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } + CallableObjectInternal getFunction() { this = TBoundMethod(_, result) } - CallableObjectInternal getFunction() { - this = TBoundMethod(_, result) - } - - ObjectInternal getSelf() { - this = TBoundMethod(result, _) - } + ObjectInternal getSelf() { this = TBoundMethod(result, _) } override string toString() { result = "Method(" + this.getFunction() + ", " + this.getSelf() + ")" @@ -443,9 +398,7 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { result = TBuiltinClassObject(Builtin::special("MethodType")) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } @@ -457,43 +410,41 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { this.getFunction().callResult(obj, origin) } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate calleeAndOffset(Function scope, int paramOffset) { - this.getFunction().calleeAndOffset(scope, paramOffset-1) + this.getFunction().calleeAndOffset(scope, paramOffset - 1) } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } - override Function getScope() { - result = this.getFunction().getScope() - } + override Function getScope() { result = this.getFunction().getScope() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override CallNode getACall(PointsToContext ctx) { PointsTo::pointsTo(result.getFunction(), ctx, this, _) } - override NameNode getParameter(int n) { - result = this.getFunction().getParameter(n+1) - } + override NameNode getParameter(int n) { result = this.getFunction().getParameter(n + 1) } override NameNode getParameterByName(string name) { result = this.getFunction().getParameterByName(name) } - override predicate neverReturns() { - this.getFunction().neverReturns() - } + override predicate neverReturns() { this.getFunction().neverReturns() } override predicate functionAndOffset(CallableObjectInternal function, int offset) { function = this.getFunction() and offset = 1 @@ -501,10 +452,7 @@ class BoundMethodObjectInternal extends CallableObjectInternal, TBoundMethod { override predicate useOriginAsLegacyObject() { any() } - override predicate contextSensitiveCallee() { - this.getFunction().contextSensitiveCallee() - } + override predicate contextSensitiveCallee() { this.getFunction().contextSensitiveCallee() } override predicate isNotSubscriptedType() { any() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/objects/Classes.qll b/python/ql/src/semmle/python/objects/Classes.qll index 1e872e70c76..b509268a80a 100644 --- a/python/ql/src/semmle/python/objects/Classes.qll +++ b/python/ql/src/semmle/python/objects/Classes.qll @@ -1,6 +1,4 @@ import python - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -10,19 +8,16 @@ private import semmle.python.types.Builtins /** Class representing classes */ abstract class ClassObjectInternal extends ObjectInternal { + override string getName() { result = this.getClassDeclaration().getName() } - override string getName() { - result = this.getClassDeclaration().getName() - } - - /** Holds if this is a class whose instances we treat specially, rather than as a generic instance. + /** + * Holds if this is a class whose instances we treat specially, rather than as a generic instance. * For example, `type` or `int`. */ - boolean isSpecial() { - result = Types::getMro(this).containsSpecial() - } + boolean isSpecial() { result = Types::getMro(this).containsSpecial() } - /** Looks up the attribute `name` on this class. + /** + * Looks up the attribute `name` on this class. * Note that this may be different from `this.attr(name)`. * For example given the class: * ```class C: @@ -51,11 +46,20 @@ abstract class ClassObjectInternal extends ObjectInternal { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { instance = this and PointsToInternal::attributeRequired(this, name) and this.lookup(name, descriptor, _) and @@ -63,11 +67,14 @@ abstract class ClassObjectInternal extends ObjectInternal { } /** Approximation to descriptor protocol, skipping meta-descriptor protocol */ - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { exists(ObjectInternal descriptor, CfgOrigin desc_origin | - this.lookup(name, descriptor, desc_origin) | + this.lookup(name, descriptor, desc_origin) + | descriptor.isDescriptor() = false and - value = descriptor and origin = desc_origin + value = descriptor and + origin = desc_origin or descriptor.isDescriptor() = true and descriptor.descriptorGetClass(this, value, origin) @@ -80,13 +87,9 @@ abstract class ClassObjectInternal extends ObjectInternal { override boolean isClass() { result = true } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } override predicate subscriptUnknown() { none() } @@ -104,12 +107,10 @@ abstract class ClassObjectInternal extends ObjectInternal { } override predicate isNotSubscriptedType() { any() } - } /** Class representing Python source classes */ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject { - /** Gets the scope for this Python class */ Class getScope() { exists(ClassExpr expr | @@ -118,34 +119,24 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject ) } - override string toString() { - result = "class " + this.getScope().getName() - } + override string toString() { result = "class " + this.getScope().getName() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonClassObject(node) and context.appliesTo(node) } - override ClassDecl getClassDeclaration() { - this = TPythonClassObject(result) - } + override ClassDecl getClassDeclaration() { this = TPythonClassObject(result) } - override ObjectInternal getClass() { - result = Types::getMetaClass(this) - } + override ObjectInternal getClass() { result = Types::getMetaClass(this) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonClassObject(result) - } + override ControlFlowNode getOrigin() { this = TPythonClassObject(result) } override predicate calleeAndOffset(Function scope, int paramOffset) { exists(PythonFunctionObjectInternal init | this.lookup("__init__", init, _) and - init.calleeAndOffset(scope, paramOffset-1) + init.calleeAndOffset(scope, paramOffset - 1) ) } @@ -153,7 +144,8 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -169,27 +161,17 @@ class PythonClassObjectInternal extends ClassObjectInternal, TPythonClassObject override predicate functionAndOffset(CallableObjectInternal function, int offset) { this.lookup("__init__", function, _) and offset = 1 } - } /** Class representing built-in classes, except `type` */ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObject { + override Builtin getBuiltin() { this = TBuiltinClassObject(result) } - override Builtin getBuiltin() { - this = TBuiltinClassObject(result) - } + override string toString() { result = "builtin-class " + this.getBuiltin().getName() } - override string toString() { - result = "builtin-class " + this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } - - override ClassDecl getClassDeclaration() { - this = TBuiltinClassObject(result) - } + override ClassDecl getClassDeclaration() { this = TBuiltinClassObject(result) } override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) @@ -198,19 +180,16 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec result = TType() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -222,33 +201,21 @@ class BuiltinClassObjectInternal extends ClassObjectInternal, TBuiltinClassObjec } override predicate notTestableForEquality() { none() } - } /** A class representing an unknown class */ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass { + override string toString() { result = "Unknown class" } - override string toString() { - result = "Unknown class" - } + override ClassDecl getClassDeclaration() { result = Builtin::unknownType() } - override ClassDecl getClassDeclaration() { - result = Builtin::unknownType() - } + override ObjectInternal getClass() { result = this } - override ObjectInternal getClass() { - result = this - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } - override Builtin getBuiltin() { - result = Builtin::unknownType() - } + override Builtin getBuiltin() { result = Builtin::unknownType() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -258,134 +225,94 @@ class UnknownClassInternal extends ClassObjectInternal, TUnknownClass { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - none() - } - - pragma [noinline] override predicate attributesUnknown() { any() } + override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate attributesUnknown() { any() } } /** A class representing the built-in class `type`. */ class TypeInternal extends ClassObjectInternal, TType { + override string toString() { result = "builtin-class type" } - override string toString() { - result = "builtin-class type" - } + override ClassDecl getClassDeclaration() { result = Builtin::special("type") } - override ClassDecl getClassDeclaration() { - result = Builtin::special("type") - } + override ObjectInternal getClass() { result = this } - override ObjectInternal getClass() { - result = this - } - - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } - override Builtin getBuiltin() { - result = Builtin::special("type") - } + override Builtin getBuiltin() { result = Builtin::special("type") } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { - none() - } + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { Types::getMro(this).lookup(name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { any() } - + pragma[noinline] + override predicate attributesUnknown() { any() } } /** A class representing a dynamically created class `type(name, *args, **kwargs)`. */ class DynamicallyCreatedClass extends ClassObjectInternal, TDynamicClass { + override string toString() { result = this.getOrigin().getNode().toString() } - override string toString() { - result = this.getOrigin().getNode().toString() - } - - override ObjectInternal getClass() { - this = TDynamicClass(_, result, _) - } + override ObjectInternal getClass() { this = TDynamicClass(_, result, _) } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { - none() - } + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } override predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - exists(ClassObjectInternal decl | - decl = Types::getMro(this).findDeclaringClass(name) | + exists(ClassObjectInternal decl | decl = Types::getMro(this).findDeclaringClass(name) | Types::declaredAttribute(decl, name, value, origin) ) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TDynamicClass(result, _, _) - } + override ControlFlowNode getOrigin() { this = TDynamicClass(result, _, _) } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TDynamicClass(node, _, context) } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate notTestableForEquality() { none() } override ClassDecl getClassDeclaration() { none() } - } class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { + ObjectInternal getGeneric() { this = TSubscriptedType(result, _) } - ObjectInternal getGeneric() { - this = TSubscriptedType(result, _) - } - - ObjectInternal getSpecializer() { - this = TSubscriptedType(_, result) - } + ObjectInternal getSpecializer() { this = TSubscriptedType(_, result) } override string getName() { result = this.getGeneric().getName() } - override string toString() { result = this.getGeneric().toString() + "[" + this.getSpecializer().toString() + "]" } + override string toString() { + result = this.getGeneric().toString() + "[" + this.getSpecializer().toString() + "]" + } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { exists(ObjectInternal generic, ObjectInternal index | @@ -395,16 +322,12 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { } /** Gets the class declaration for this object, if it is a class with a declaration. */ - override ClassDecl getClassDeclaration() { - result = this.getGeneric().getClassDeclaration() - } + override ClassDecl getClassDeclaration() { result = this.getGeneric().getClassDeclaration() } /** True if this "object" is a class. That is, its class inherits from `type` */ override boolean isClass() { result = true } - override ObjectInternal getClass() { - result = this.getGeneric().getClass() - } + override ObjectInternal getClass() { result = this.getGeneric().getClass() } override predicate notTestableForEquality() { none() } @@ -414,9 +337,11 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - override predicate calleeAndOffset(Function scope, int paramOffset){ none() } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } @@ -424,17 +349,25 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override boolean isDescriptor() { result = false } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override boolean booleanValue() { result = true } - override int intValue() { none()} + override int intValue() { none() } override string strValue() { none() } @@ -448,8 +381,4 @@ class SubscriptedTypeInternal extends ObjectInternal, TSubscriptedType { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { none() } - } - - - diff --git a/python/ql/src/semmle/python/objects/Constants.qll b/python/ql/src/semmle/python/objects/Constants.qll index 1b93a3bb6f2..8cc0911af53 100644 --- a/python/ql/src/semmle/python/objects/Constants.qll +++ b/python/ql/src/semmle/python/objects/Constants.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -7,16 +6,13 @@ private import semmle.python.pointsto.MRO private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins - -/** Class representing constants. +/** + * Class representing constants. * Includes `None`, `True` and `False` as * well as strings and integers. */ abstract class ConstantObjectInternal extends ObjectInternal { - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } @@ -32,33 +28,41 @@ abstract class ConstantObjectInternal extends ObjectInternal { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig) and - cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) + cls_attr.isDescriptor() = true and + cls_attr.descriptorGetInstance(this, value, origin) ) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(ClassObjectInternal cls | receiver_type(_, name, this, cls) and cls.lookup(name, descriptor, _) and @@ -77,29 +81,23 @@ abstract class ConstantObjectInternal extends ObjectInternal { abstract ImmutableLiteral getLiteral(); override predicate isNotSubscriptedType() { any() } - } pragma[nomagic] private boolean callToBool(CallNode call, PointsToContext context) { PointsToInternal::pointsTo(call.getFunction(), context, ClassValue::bool(), _) and exists(ObjectInternal arg | - PointsToInternal::pointsTo(call.getArg(0),context, arg, _) and + PointsToInternal::pointsTo(call.getArg(0), context, arg, _) and arg.booleanValue() = result ) } -private abstract class BooleanObjectInternal extends ConstantObjectInternal { - - override ObjectInternal getClass() { - result = ClassValue::bool() - } +abstract private class BooleanObjectInternal extends ConstantObjectInternal { + override ObjectInternal getClass() { result = ClassValue::bool() } override int length() { none() } - override string strValue() { - none() - } + override string strValue() { none() } /* Booleans aren't iterable */ override ObjectInternal getIterNext() { none() } @@ -107,18 +105,12 @@ private abstract class BooleanObjectInternal extends ConstantObjectInternal { override ImmutableLiteral getLiteral() { result.(BooleanLiteral).booleanValue() = this.booleanValue() } - } private class TrueObjectInternal extends BooleanObjectInternal, TTrue { + override string toString() { result = "bool True" } - override string toString() { - result = "bool True" - } - - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "True" and context.appliesTo(node) @@ -126,25 +118,15 @@ private class TrueObjectInternal extends BooleanObjectInternal, TTrue { callToBool(node, context) = true } - override int intValue() { - result = 1 - } - - override Builtin getBuiltin() { - result = Builtin::special("True") - } + override int intValue() { result = 1 } + override Builtin getBuiltin() { result = Builtin::special("True") } } private class FalseObjectInternal extends BooleanObjectInternal, TFalse { + override string toString() { result = "bool False" } - override string toString() { - result = "bool False" - } - - override boolean booleanValue() { - result = false - } + override boolean booleanValue() { result = false } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "False" and context.appliesTo(node) @@ -152,84 +134,51 @@ private class FalseObjectInternal extends BooleanObjectInternal, TFalse { callToBool(node, context) = false } - override int intValue() { - result = 0 - } - - override Builtin getBuiltin() { - result = Builtin::special("False") - } + override int intValue() { result = 0 } + override Builtin getBuiltin() { result = Builtin::special("False") } } private class NoneObjectInternal extends ConstantObjectInternal, TNone { + override string toString() { result = "None" } - override string toString() { - result = "None" - } + override boolean booleanValue() { result = false } - override boolean booleanValue() { - result = false - } - - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("NoneType")) } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { node.(NameNode).getId() = "None" and context.appliesTo(node) } - override Builtin getBuiltin() { - result = Builtin::special("None") - } + override Builtin getBuiltin() { result = Builtin::special("None") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } override int length() { none() } /* None isn't iterable */ override ObjectInternal getIterNext() { none() } - override ImmutableLiteral getLiteral() { - result instanceof None - } - + override ImmutableLiteral getLiteral() { result instanceof None } } - class IntObjectInternal extends ConstantObjectInternal, TInt { - - override string toString() { - result = "int " + this.intValue().toString() - } + override string toString() { result = "int " + this.intValue().toString() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and node.getNode().(IntegerLiteral).getValue() = this.intValue() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("int")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("int")) } - override Builtin getBuiltin() { - result.intValue() = this.intValue() - } + override Builtin getBuiltin() { result.intValue() = this.intValue() } - override int intValue() { - this = TInt(result) - } + override int intValue() { this = TInt(result) } - override string strValue() { - none() - } + override string strValue() { none() } override boolean booleanValue() { this.intValue() = 0 and result = false @@ -247,17 +196,13 @@ class IntObjectInternal extends ConstantObjectInternal, TInt { or result.(NegativeIntegerLiteral).getOperand().(IntegerLiteral).getValue() = -this.intValue() } - } class FloatObjectInternal extends ConstantObjectInternal, TFloat { - override string toString() { - if this.floatValue() = this.floatValue().floor() then ( - result = "float " + this.floatValue().floor().toString() + ".0" - ) else ( - result = "float " + this.floatValue().toString() - ) + if this.floatValue() = this.floatValue().floor() + then result = "float " + this.floatValue().floor().toString() + ".0" + else result = "float " + this.floatValue().toString() } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { @@ -265,25 +210,15 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat { node.getNode().(FloatLiteral).getValue() = this.floatValue() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("float")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("float")) } - override Builtin getBuiltin() { - result.floatValue() = this.floatValue() - } + override Builtin getBuiltin() { result.floatValue() = this.floatValue() } - float floatValue() { - this = TFloat(result) - } + float floatValue() { this = TFloat(result) } - override int intValue() { - this = TFloat(result) - } + override int intValue() { this = TFloat(result) } - override string strValue() { - none() - } + override string strValue() { none() } override boolean booleanValue() { this.floatValue() = 0.0 and result = false @@ -296,18 +231,11 @@ class FloatObjectInternal extends ConstantObjectInternal, TFloat { /* floats aren't iterable */ override ObjectInternal getIterNext() { none() } - override ImmutableLiteral getLiteral() { - result.(FloatLiteral).getValue() = this.floatValue() - } - + override ImmutableLiteral getLiteral() { result.(FloatLiteral).getValue() = this.floatValue() } } - class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { - - override string toString() { - result = "'" + this.strValue() + "'" - } + override string toString() { result = "'" + this.strValue() + "'" } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and @@ -315,22 +243,16 @@ class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { node.getNode().(StrConst).isUnicode() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("unicode")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("unicode")) } override Builtin getBuiltin() { result.(Builtin).strValue() = this.strValue() and result.getClass() = Builtin::special("unicode") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - this = TUnicode(result) - } + override string strValue() { this = TUnicode(result) } override boolean booleanValue() { this.strValue() = "" and result = false @@ -338,25 +260,15 @@ class UnicodeObjectInternal extends ConstantObjectInternal, TUnicode { this.strValue() != "" and result = true } - override int length() { - result = this.strValue().length() - } + override int length() { result = this.strValue().length() } - override ObjectInternal getIterNext() { - result = TUnknownInstance(this.getClass()) - } - - override ImmutableLiteral getLiteral() { - result.(Unicode).getText() = this.strValue() - } + override ObjectInternal getIterNext() { result = TUnknownInstance(this.getClass()) } + override ImmutableLiteral getLiteral() { result.(Unicode).getText() = this.strValue() } } class BytesObjectInternal extends ConstantObjectInternal, TBytes { - - override string toString() { - result = "'" + this.strValue() + "'" - } + override string toString() { result = "'" + this.strValue() + "'" } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { context.appliesTo(node) and @@ -364,22 +276,16 @@ class BytesObjectInternal extends ConstantObjectInternal, TBytes { not node.getNode().(StrConst).isUnicode() } - override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("bytes")) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(Builtin::special("bytes")) } override Builtin getBuiltin() { result.(Builtin).strValue() = this.strValue() and result.getClass() = Builtin::special("bytes") } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - this = TBytes(result) - } + override string strValue() { this = TBytes(result) } override boolean booleanValue() { this.strValue() = "" and result = false @@ -387,20 +293,9 @@ class BytesObjectInternal extends ConstantObjectInternal, TBytes { this.strValue() != "" and result = true } - override int length() { - result = this.strValue().length() - } + override int length() { result = this.strValue().length() } - override ObjectInternal getIterNext() { - result = TUnknownInstance(this.getClass()) - } - - override ImmutableLiteral getLiteral() { - result.(Bytes).getText() = this.strValue() - } + override ObjectInternal getIterNext() { result = TUnknownInstance(this.getClass()) } + override ImmutableLiteral getLiteral() { result.(Bytes).getText() = this.strValue() } } - - - - diff --git a/python/ql/src/semmle/python/objects/Descriptors.qll b/python/ql/src/semmle/python/objects/Descriptors.qll index dbc3e59afa5..ece746d8625 100644 --- a/python/ql/src/semmle/python/objects/Descriptors.qll +++ b/python/ql/src/semmle/python/objects/Descriptors.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -9,16 +8,11 @@ private import semmle.python.types.Builtins /** Class representing property objects in Python */ class PropertyInternal extends ObjectInternal, TProperty { - /** Gets the name of this property */ - override string getName() { - result = this.getGetter().getName() - } + override string getName() { result = this.getGetter().getName() } /** Gets the getter function of this property */ - CallableObjectInternal getGetter() { - this = TProperty(_, _, result) - } + CallableObjectInternal getGetter() { this = TProperty(_, _, result) } private CallNode getCallNode() { this = TProperty(result, _, _) } @@ -55,11 +49,9 @@ class PropertyInternal extends ObjectInternal, TProperty { ) } - private Context getContext() { this = TProperty(_,result, _) } + private Context getContext() { this = TProperty(_, result, _) } - override string toString() { - result = "property " + this.getName() - } + override string toString() { result = "property " + this.getName() } override boolean booleanValue() { result = true } @@ -79,7 +71,9 @@ class PropertyInternal extends ObjectInternal, TProperty { override ControlFlowNode getOrigin() { this = TProperty(result, _, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -89,7 +83,8 @@ class PropertyInternal extends ObjectInternal, TProperty { override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = TPropertySetterOrDeleter(this, name) and origin = CfgOrigin::unknown() } @@ -103,20 +98,28 @@ class PropertyInternal extends ObjectInternal, TProperty { override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { none() } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this and origin = CfgOrigin::fromCfgNode(this.getOrigin()) + value = this and + origin = CfgOrigin::fromCfgNode(this.getOrigin()) } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { - /* Just give an unknown value for now. We could improve this, but it would mean + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + /* + * Just give an unknown value for now. We could improve this, but it would mean * changing Contexts to account for property accesses. */ + exists(ClassObjectInternal cls, string name | name = this.getName() and receiver_type(_, name, instance, cls) and cls.lookup(name, this, _) and - origin = CfgOrigin::unknown() and value = ObjectInternal::unknown() + origin = CfgOrigin::unknown() and + value = ObjectInternal::unknown() ) } @@ -128,40 +131,31 @@ class PropertyInternal extends ObjectInternal, TProperty { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrDeleter { + override string toString() { result = this.getProperty().toString() + "." + this.getName() } - override string toString() { - result = this.getProperty().toString() + "." + this.getName() - } + override string getName() { this = TPropertySetterOrDeleter(_, result) } - override string getName() { - this = TPropertySetterOrDeleter(_, result) - } - - PropertyInternal getProperty() { - this = TPropertySetterOrDeleter(result, _) - } + PropertyInternal getProperty() { this = TPropertySetterOrDeleter(result, _) } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { exists(ControlFlowNode call | - obj = this.getProperty() and obj = TProperty(call, _, _) and + obj = this.getProperty() and + obj = TProperty(call, _, _) and origin = CfgOrigin::fromCfgNode(call) ) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override ObjectInternal getClass() { - result = TBuiltinClassObject(Builtin::special("MethodType")) + result = TBuiltinClassObject(Builtin::special("MethodType")) } override predicate notTestableForEquality() { none() } @@ -170,7 +164,9 @@ private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrD override ControlFlowNode getOrigin() { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override int intValue() { none() } @@ -196,23 +192,24 @@ private class PropertySetterOrDeleter extends ObjectInternal, TPropertySetterOrD override ObjectInternal getIterNext() { none() } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } - /** A class representing classmethods in Python */ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { - - override string toString() { - result = "classmethod(" + this.getFunction() + ")" - } + override string toString() { result = "classmethod(" + this.getFunction() + ")" } override boolean booleanValue() { result = true } @@ -224,9 +221,7 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { } /** Gets the function wrapped by this classmethod object */ - CallableObjectInternal getFunction() { - this = TClassMethod(_, result) - } + CallableObjectInternal getFunction() { this = TClassMethod(_, result) } override ClassDecl getClassDeclaration() { none() } @@ -240,7 +235,9 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override ControlFlowNode getOrigin() { this = TClassMethod(result, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -258,26 +255,31 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { value = TBoundMethod(cls, this.getFunction()) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { any(ObjectInternal obj).binds(instance, _, this) and value = TBoundMethod(instance.getClass(), this.getFunction()) and origin = CfgOrigin::unknown() } - /** Holds if attribute lookup on this object may "bind" `cls` to `descriptor`. + /** + * Holds if attribute lookup on this object may "bind" `cls` to `descriptor`. * `cls` will always be a class as this is a classmethod. * Here "bind" means that `instance` is passed to the `classmethod.__get__()` method * at runtime. The term "bind" is used as this most likely results in a bound-method. */ - pragma [noinline] override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal cls, string name, ObjectInternal descriptor) { descriptor = this.getFunction() and - exists(ObjectInternal instance | - any(ObjectInternal obj).binds(instance, name, this) | + exists(ObjectInternal instance | any(ObjectInternal obj).binds(instance, name, this) | instance.isClass() = false and cls = instance.getClass() or instance.isClass() = true and cls = instance @@ -286,9 +288,7 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override int length() { none() } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } override predicate contextSensitiveCallee() { none() } @@ -298,14 +298,10 @@ class ClassMethodObjectInternal extends ObjectInternal, TClassMethod { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { - - override string toString() { - result = "staticmethod()" - } + override string toString() { result = "staticmethod()" } override boolean booleanValue() { result = true } @@ -316,9 +312,7 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { ) } - CallableObjectInternal getFunction() { - this = TStaticMethod(_, result) - } + CallableObjectInternal getFunction() { this = TStaticMethod(_, result) } override ClassDecl getClassDeclaration() { none() } @@ -332,7 +326,9 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override ControlFlowNode getOrigin() { this = TStaticMethod(result, _) } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } @@ -352,23 +348,29 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override boolean isDescriptor() { result = true } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { any(ObjectInternal obj).binds(cls, _, this) and - value = this.getFunction() and origin = CfgOrigin::unknown() + value = this.getFunction() and + origin = CfgOrigin::unknown() } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { any(ObjectInternal obj).binds(instance, _, this) and - value = this.getFunction() and origin = CfgOrigin::unknown() + value = this.getFunction() and + origin = CfgOrigin::unknown() } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } - override string getName() { - result = this.getFunction().getName() - } + override string getName() { result = this.getFunction().getName() } override predicate contextSensitiveCallee() { none() } @@ -378,5 +380,4 @@ class StaticMethodObjectInternal extends ObjectInternal, TStaticMethod { override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/Instances.qll b/python/ql/src/semmle/python/objects/Instances.qll index ab5a12b5070..396e26d8aad 100644 --- a/python/ql/src/semmle/python/objects/Instances.qll +++ b/python/ql/src/semmle/python/objects/Instances.qll @@ -1,6 +1,4 @@ import python - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -10,18 +8,19 @@ private import semmle.python.types.Builtins /** A class representing instances */ abstract class InstanceObject extends ObjectInternal { - - pragma [nomagic] + pragma[nomagic] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - exists(ObjectInternal cls_attr | - this.classAttribute(name, cls_attr) - | - /* If class attribute is not a descriptor, that usually means it is some sort of + exists(ObjectInternal cls_attr | this.classAttribute(name, cls_attr) | + /* + * If class attribute is not a descriptor, that usually means it is some sort of * default value and likely overridden by an instance attribute. In that case * use `unknown` to signal that an attribute exists but to avoid false positives * f using the default value. */ - cls_attr.isDescriptor() = false and value = ObjectInternal::unknown() and origin = CfgOrigin::unknown() + + cls_attr.isDescriptor() = false and + value = ObjectInternal::unknown() and + origin = CfgOrigin::unknown() or cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) ) @@ -29,13 +28,13 @@ abstract class InstanceObject extends ObjectInternal { this.selfAttribute(name, value, origin) } - pragma [noinline] + pragma[noinline] private predicate classAttribute(string name, ObjectInternal cls_attr) { PointsToInternal::attributeRequired(this, name) and this.getClass().(ClassObjectInternal).lookup(name, cls_attr, _) } - pragma [noinline] + pragma[noinline] private predicate selfAttribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(EssaVariable self, PythonFunctionObjectInternal init, Context callee | @@ -56,7 +55,6 @@ abstract class InstanceObject extends ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } private predicate self_variable_reaching_init_exit(EssaVariable self) { @@ -65,14 +63,12 @@ private predicate self_variable_reaching_init_exit(EssaVariable self) { self.getScope().getName() = "__init__" } -/** A class representing instances instantiated at a specific point in the program (statically) +/** + * A class representing instances instantiated at a specific point in the program (statically) * For example the code `C()` would be a specific instance of `C`. */ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { - - override string toString() { - result = this.getOrigin().getNode().toString() - } + override string toString() { result = this.getOrigin().getNode().toString() } override boolean booleanValue() { //result = this.getClass().instancesBooleanValue() @@ -84,9 +80,7 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } @@ -95,64 +89,65 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { override ObjectInternal getClass() { exists(ClassObjectInternal cls, ClassDecl decl | this = TSpecificInstance(_, cls, _) and - decl = cls.getClassDeclaration() | - if decl.callReturnsInstance() then - result = cls - else - result = TUnknownClass() + decl = cls.getClassDeclaration() + | + if decl.callReturnsInstance() then result = cls else result = TUnknownClass() ) } - /** Gets the `Builtin` for this object, if any. - * All objects (except unknown and undefined values) should return + /** + * Gets the `Builtin` for this object, if any. + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getOrigin()`. */ - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. - * All objects (except unknown and undefined values) should return + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getBuiltin()`. */ - override ControlFlowNode getOrigin() { - this = TSpecificInstance(result, _, _) - } + override ControlFlowNode getOrigin() { this = TSpecificInstance(result, _, _) } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { // TO DO -- Handle cases where class overrides __call__ in more detail, like normal calls. this.getClass().(ClassObjectInternal).lookup("__call__", _, _) and - obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() + obj = ObjectInternal::unknown() and + origin = CfgOrigin::unknown() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(ClassObjectInternal cls | receiver_type(_, name, this, cls) and cls.lookup(name, descriptor, _) and @@ -161,9 +156,7 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { this = instance } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override predicate initializer(PythonFunctionObjectInternal init, Context callee) { exists(CallNode call, Context caller, ClassObjectInternal cls | @@ -174,13 +167,12 @@ class SpecificInstanceInternal extends TSpecificInstance, InstanceObject { } override predicate useOriginAsLegacyObject() { none() } - } -/** A class representing context-free instances represented by `self` in the source code +/** + * A class representing context-free instances represented by `self` in the source code */ class SelfInstanceInternal extends TSelfInstance, InstanceObject { - override string toString() { result = "self instance of " + this.getClass().(ClassObjectInternal).getName() } @@ -191,34 +183,24 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { result = maybe() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } predicate parameterAndContext(ParameterDefinition def, PointsToContext context) { this = TSelfInstance(def, context, _) } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - this = TSelfInstance(_, _, result) - } + override ObjectInternal getClass() { this = TSelfInstance(_, _, result) } - ParameterDefinition getParameter() { - this = TSelfInstance(result, _, _) - } + ParameterDefinition getParameter() { this = TSelfInstance(result, _, _) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override ControlFlowNode getOrigin() { exists(ParameterDefinition def | @@ -231,35 +213,39 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { none() } - override predicate callResult(ObjectInternal obj, CfgOrigin origin) { + override predicate callResult(ObjectInternal obj, CfgOrigin origin) { // In general instances aren't callable, but some are... // TO DO -- Handle cases where class overrides __call__ none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(AttrNode attr, ClassObjectInternal cls | receiver_type(attr, name, this, cls) and cls_descriptor(cls, name, descriptor) @@ -267,9 +253,7 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { instance = this } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override predicate initializer(PythonFunctionObjectInternal init, Context callee) { callee.isRuntime() and @@ -278,53 +262,41 @@ class SelfInstanceInternal extends TSelfInstance, InstanceObject { } override predicate useOriginAsLegacyObject() { none() } - } /** A class representing a value that has a known class, but no other information */ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { - override string toString() { result = "instance of " + this.getClass().(ClassObjectInternal).getName() } - override boolean booleanValue() { - result = maybe() - } + override boolean booleanValue() { result = maybe() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } /** Gets the class declaration for this object, if it is a declared class. */ - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - this = TUnknownInstance(result) - } + override ObjectInternal getClass() { this = TUnknownInstance(result) } - /** Gets the `Builtin` for this object, if any. - * All objects (except unknown and undefined values) should return + /** + * Gets the `Builtin` for this object, if any. + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getOrigin()`. */ - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. - * All objects (except unknown and undefined values) should return + * All objects (except unknown and undefined values) should return * exactly one result for either this method or `getBuiltin()`. */ - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -336,40 +308,45 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { PointsToInternal::attributeRequired(this, name) and exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.getClass().(ClassObjectInternal).lookup(name, cls_attr, attr_orig) - | + | cls_attr.isDescriptor() = false and value = cls_attr and origin = attr_orig or cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this, value, origin) ) } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { exists(AttrNode attr, ClassObjectInternal cls | receiver_type(attr, name, this, cls) and cls_descriptor(cls, name, descriptor) @@ -377,9 +354,7 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { instance = this } - override int length() { - result = lengthFromClass(this.getClass()) - } + override int length() { result = lengthFromClass(this.getClass()) } override string getName() { none() } @@ -390,7 +365,6 @@ class UnknownInstanceInternal extends TUnknownInstance, ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } private int lengthFromClass(ClassObjectInternal cls) { @@ -404,7 +378,6 @@ private predicate cls_descriptor(ClassObjectInternal cls, string name, ObjectInt /** A class representing an instance of the `super` class */ class SuperInstance extends TSuperInstance, ObjectInternal { - override string toString() { result = "super(" + this.getStartClass().toString() + ", " + this.getSelf().toString() + ")" } @@ -419,34 +392,28 @@ class SuperInstance extends TSuperInstance, ObjectInternal { } /** Gets the class declared as the starting point for MRO lookup. */ - ClassObjectInternal getStartClass() { - this = TSuperInstance(_, result) - } + ClassObjectInternal getStartClass() { this = TSuperInstance(_, result) } /** Gets 'self' object */ - ObjectInternal getSelf() { - this = TSuperInstance(result, _) - } + ObjectInternal getSelf() { this = TSuperInstance(result, _) } override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = ObjectInternal::superType() - } + override ObjectInternal getClass() { result = ObjectInternal::superType() } override predicate notTestableForEquality() { any() } override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } override int intValue() { none() } @@ -454,46 +421,60 @@ class SuperInstance extends TSuperInstance, ObjectInternal { override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { exists(ObjectInternal cls_attr, CfgOrigin attr_orig | this.attribute_descriptor(name, cls_attr, attr_orig) - | + | cls_attr.isDescriptor() = false and value = cls_attr and origin = attr_orig or - cls_attr.isDescriptor() = true and cls_attr.descriptorGetInstance(this.getSelf(), value, origin) + cls_attr.isDescriptor() = true and + cls_attr.descriptorGetInstance(this.getSelf(), value, origin) ) } /* Helper for `attribute` */ - pragma [noinline] private predicate attribute_descriptor(string name, ObjectInternal cls_attr, CfgOrigin attr_orig) { + pragma[noinline] + private predicate attribute_descriptor(string name, ObjectInternal cls_attr, CfgOrigin attr_orig) { PointsToInternal::attributeRequired(this, name) and this.lookup(name, cls_attr, attr_orig) } private predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - Types::getMro(this.getSelf().getClass()).startingAt(this.getStartClass()).getTail().lookup(name, value, origin) + Types::getMro(this.getSelf().getClass()) + .startingAt(this.getStartClass()) + .getTail() + .lookup(name, value, origin) } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { descriptor.isDescriptor() = true and this.lookup(name, descriptor, _) and instance = this.getSelf() and receiver_type(_, name, this, _) } - override int length() { - none() - } + override int length() { none() } override string getName() { none() } @@ -504,6 +485,4 @@ class SuperInstance extends TSuperInstance, ObjectInternal { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } - diff --git a/python/ql/src/semmle/python/objects/Modules.qll b/python/ql/src/semmle/python/objects/Modules.qll index fdc748ae0e9..83b8fb5769c 100644 --- a/python/ql/src/semmle/python/objects/Modules.qll +++ b/python/ql/src/semmle/python/objects/Modules.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -9,7 +8,6 @@ private import semmle.python.types.Builtins /** A class representing modules */ abstract class ModuleObjectInternal extends ObjectInternal { - /** Gets the source scope of this module, if it has one. */ abstract Module getSourceModule(); @@ -27,30 +25,35 @@ abstract class ModuleObjectInternal extends ObjectInternal { override predicate notTestableForEquality() { none() } - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } - override ObjectInternal getClass() { - result = ObjectInternal::moduleType() - } + override ObjectInternal getClass() { result = ObjectInternal::moduleType() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override predicate subscriptUnknown() { any() } /** Holds if this module is a `__init__.py` module. */ - predicate isInitModule() { - any(PackageObjectInternal package).getInitModule() = this - } + predicate isInitModule() { any(PackageObjectInternal package).getInitModule() = this } override predicate contextSensitiveCallee() { none() } @@ -59,14 +62,16 @@ abstract class ModuleObjectInternal extends ObjectInternal { /* Modules aren't iterable */ override ObjectInternal getIterNext() { none() } - /** Holds if this module "exports" name. + /** + * Holds if this module "exports" name. * That is, does it define `name` in `__all__` or is * `__all__` not defined and `name` a global variable that does not start with "_" * This is the set of names imported by `from ... import *`. */ predicate exports(string name) { - not this.(ModuleObjectInternal).attribute("__all__", _, _) and this.hasAttribute(name) - and not name.charAt(0) = "_" + not this.(ModuleObjectInternal).attribute("__all__", _, _) and + this.hasAttribute(name) and + not name.charAt(0) = "_" or py_exports(this.getSourceModule(), name) } @@ -75,101 +80,61 @@ abstract class ModuleObjectInternal extends ObjectInternal { abstract predicate hasCompleteExportInfo(); override predicate isNotSubscriptedType() { any() } - } /** A class representing built-in modules */ class BuiltinModuleObjectInternal extends ModuleObjectInternal, TBuiltinModuleObject { + override Builtin getBuiltin() { this = TBuiltinModuleObject(result) } - override Builtin getBuiltin() { - this = TBuiltinModuleObject(result) - } + override string toString() { result = "Module " + this.getBuiltin().getName() } - override string toString() { - result = "Module " + this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } - override string getName() { - result = this.getBuiltin().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override ClassDecl getClassDeclaration() { none() } - override ClassDecl getClassDeclaration() { - none() - } + override Module getSourceModule() { none() } - override Module getSourceModule() { - none() - } + override int intValue() { none() } - override int intValue() { - none() - } + override string strValue() { none() } - override string strValue() { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } - - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - none() - } - - override predicate hasCompleteExportInfo() { - any() - } + override ControlFlowNode getOrigin() { none() } + override predicate hasCompleteExportInfo() { any() } } /** A class representing packages */ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } - - override string toString() { - result = "Package " + this.getName() - } + override string toString() { result = "Package " + this.getName() } /** Gets the folder for this package */ - Folder getFolder() { - this = TPackageObject(result) - } + Folder getFolder() { this = TPackageObject(result) } - override string getName() { - result = moduleNameFromFile(this.getFolder()) - } + override string getName() { result = moduleNameFromFile(this.getFolder()) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override Module getSourceModule() { - result.getFile() = this.getFolder().getFile("__init__.py") - } + override Module getSourceModule() { result.getFile() = this.getFolder().getFile("__init__.py") } /** Gets the init module of this package */ - PythonModuleObjectInternal getInitModule() { - result = TPythonModule(this.getSourceModule()) - } + PythonModuleObjectInternal getInitModule() { result = TPythonModule(this.getSourceModule()) } predicate hasNoInitModule() { exists(Folder f | @@ -188,19 +153,14 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { ) } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { this.getInitModule().attribute(name, value, origin) or exists(Module init | @@ -215,12 +175,14 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { this.hasNoInitModule() and exists(ModuleObjectInternal mod | mod = this.submodule(name) and - value = mod | + value = mod + | origin = CfgOrigin::fromObject(mod) ) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override ControlFlowNode getOrigin() { exists(Module package | @@ -238,7 +200,6 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { } override predicate hasCompleteExportInfo() { - not exists(this.getInitModule()) or this.getInitModule().hasCompleteExportInfo() @@ -247,53 +208,34 @@ class PackageObjectInternal extends ModuleObjectInternal, TPackageObject { /** A class representing Python modules */ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule { + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } + override string toString() { result = this.getSourceModule().toString() } - override string toString() { - result = this.getSourceModule().toString() - } + override string getName() { result = this.getSourceModule().getName() } - override string getName() { - result = this.getSourceModule().getName() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override ClassDecl getClassDeclaration() { none() } - override ClassDecl getClassDeclaration() { - none() - } + override Module getSourceModule() { this = TPythonModule(result) } - override Module getSourceModule() { - this = TPythonModule(result) - } + override int intValue() { none() } - override int intValue() { - none() - } + override string strValue() { none() } - override string strValue() { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } - - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value != ObjectInternal::undefined() and ModuleAttributes::pointsToAtExit(this.getSourceModule(), name, value, origin) } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - result = this.getSourceModule().getEntryNode() - } + override ControlFlowNode getOrigin() { result = this.getSourceModule().getEntryNode() } /** Holds if this value has the attribute `name` */ override predicate hasAttribute(string name) { @@ -317,76 +259,56 @@ class PythonModuleObjectInternal extends ModuleObjectInternal, TPythonModule { not exists(Call modify, Attribute attr, GlobalVariable all | modify.getScope() = this.getSourceModule() and modify.getFunc() = attr and - all.getId() = "__all__" | + all.getId() = "__all__" + | attr.getObject().(Name).uses(all) ) } - } /** A class representing a module that is missing from the DB, but inferred to exists from imports. */ class AbsentModuleObjectInternal extends ModuleObjectInternal, TAbsentModule { - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override string toString() { - if exists(Module m, SyntaxError se | se.getFile() = m.getFile() and m.getName() = this.getName()) then - result = "Unparsable module " + this.getName() - else - result = "Missing module " + this.getName() + if + exists(Module m, SyntaxError se | se.getFile() = m.getFile() and m.getName() = this.getName()) + then result = "Unparsable module " + this.getName() + else result = "Missing module " + this.getName() } - override string getName() { - this = TAbsentModule(result) - } + override string getName() { this = TAbsentModule(result) } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { missing_imported_module(node, context, this.getName()) } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override Module getSourceModule() { - none() - } + override Module getSourceModule() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = TAbsentModuleAttribute(this, name) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override predicate hasCompleteExportInfo() { - none() - } + override predicate hasCompleteExportInfo() { none() } } /** A class representing an attribute of a missing module. */ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleAttribute { - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override string toString() { exists(ModuleObjectInternal mod, string name | @@ -396,39 +318,28 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA } override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - exists(ModuleObjectInternal mod, string name | - this = TAbsentModuleAttribute(mod, name) | + exists(ModuleObjectInternal mod, string name | this = TAbsentModuleAttribute(mod, name) | PointsToInternal::pointsTo(node.(AttrNode).getObject(name), context, mod, _) or PointsToInternal::pointsTo(node.(ImportMemberNode).getModule(name), context, mod, _) ) } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() @@ -442,31 +353,36 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA override predicate notTestableForEquality() { any() } - override boolean booleanValue() { - result = maybe() - } + override boolean booleanValue() { result = maybe() } - override ObjectInternal getClass() { - result = ObjectInternal::unknownClass() - } + override ObjectInternal getClass() { result = ObjectInternal::unknownClass() } override boolean isDescriptor() { result = false } - override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } override predicate subscriptUnknown() { any() } - /* We know what this is called, but not its innate name. - * However, if we are looking for things by name, this is a reasonable approximation */ - override string getName() { - this = TAbsentModuleAttribute(_, result) - } + /* + * We know what this is called, but not its innate name. + * However, if we are looking for things by name, this is a reasonable approximation + */ + + override string getName() { this = TAbsentModuleAttribute(_, result) } override predicate contextSensitiveCallee() { none() } @@ -476,5 +392,4 @@ class AbsentModuleAttributeObjectInternal extends ObjectInternal, TAbsentModuleA override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/ObjectAPI.qll b/python/ql/src/semmle/python/objects/ObjectAPI.qll index 498856ae668..2a5bf0a0954 100644 --- a/python/ql/src/semmle/python/objects/ObjectAPI.qll +++ b/python/ql/src/semmle/python/objects/ObjectAPI.qll @@ -3,9 +3,6 @@ * A `Value` is a static approximation to a set of runtime objects. */ - - - import python private import TObject private import semmle.python.objects.ObjectInternal @@ -14,54 +11,48 @@ private import semmle.python.pointsto.PointsToContext private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins -/* Use the term `ObjectSource` to refer to DB entity. Either a CFG node +/* + * Use the term `ObjectSource` to refer to DB entity. Either a CFG node * for Python objects, or `@py_cobject` entity for built-in objects. */ + class ObjectSource = Object; /* Aliases for scopes */ class FunctionScope = Function; + class ClassScope = Class; + class ModuleScope = Module; -/** Class representing values in the Python program +/** + * Class representing values in the Python program * Each `Value` is a static approximation to a set of one or more real objects. */ class Value extends TObject { - Value() { this != ObjectInternal::unknown() and this != ObjectInternal::unknownClass() and this != ObjectInternal::undefined() } - string toString() { - result = this.(ObjectInternal).toString() - } + string toString() { result = this.(ObjectInternal).toString() } /** Gets a `ControlFlowNode` that refers to this object. */ - ControlFlowNode getAReference() { - PointsToInternal::pointsTo(result, _, this, _) - } + ControlFlowNode getAReference() { PointsToInternal::pointsTo(result, _, this, _) } /** Gets the origin CFG node for this value. */ - ControlFlowNode getOrigin() { - result = this.(ObjectInternal).getOrigin() - } + ControlFlowNode getOrigin() { result = this.(ObjectInternal).getOrigin() } - - /** Gets the class of this object. + /** + * Gets the class of this object. * Strictly, the `Value` representing the class of the objects * represented by this Value. */ - ClassValue getClass() { - result = this.(ObjectInternal).getClass() - } + ClassValue getClass() { result = this.(ObjectInternal).getClass() } /** Gets a call to this object */ - CallNode getACall() { - result = this.getACall(_) - } + CallNode getACall() { result = this.getACall(_) } /** Gets a call to this object with the given `caller` context. */ CallNode getACall(PointsToContext caller) { @@ -74,36 +65,34 @@ class Value extends TObject { } /** Gets a `Value` that represents the attribute `name` of this object. */ - Value attr(string name) { - this.(ObjectInternal).attribute(name, result, _) - } + Value attr(string name) { this.(ObjectInternal).attribute(name, result, _) } - /** Holds if this value is builtin. Applies to built-in functions and methods, + /** + * Holds if this value is builtin. Applies to built-in functions and methods, * but also integers and strings. */ - predicate isBuiltin() { - this.(ObjectInternal).isBuiltin() - } + predicate isBuiltin() { this.(ObjectInternal).isBuiltin() } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.(ObjectInternal).getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec) or not exists(this.(ObjectInternal).getOrigin()) and - filepath = "" and bl = 0 and bc = 0 and el = 0 and ec = 0 + filepath = "" and + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } - /** Gets the name of this value, if it has one. + /** + * Gets the name of this value, if it has one. * Note this is the innate name of the * object, not necessarily all the names by which it can be called. */ - final string getName() { - result = this.(ObjectInternal).getName() - } + final string getName() { result = this.(ObjectInternal).getName() } /** Holds if this value has the attribute `name` */ - predicate hasAttribute(string name) { - this.(ObjectInternal).hasAttribute(name) - } + predicate hasAttribute(string name) { this.(ObjectInternal).hasAttribute(name) } /** Whether this value is absent from the database, but has been inferred to likely exist */ predicate isAbsent() { @@ -112,7 +101,8 @@ class Value extends TObject { this instanceof AbsentModuleAttributeObjectInternal } - /** Whether this overrides v. In this context, "overrides" means that this object + /** + * Whether this overrides v. In this context, "overrides" means that this object * is a named attribute of a some class C and `v` is a named attribute of another * class S, both attributes having the same name, and S is a super class of C. */ @@ -124,46 +114,42 @@ class Value extends TObject { ) } - /** Gets the boolean interpretation of this value. - * Could be both `true` and `false`, if we can't determine the result more precisely. - */ - boolean getABooleanValue() { - result = this.(ObjectInternal).booleanValue() - } + /** + * Gets the boolean interpretation of this value. + * Could be both `true` and `false`, if we can't determine the result more precisely. + */ + boolean getABooleanValue() { result = this.(ObjectInternal).booleanValue() } - /** Gets the boolean interpretation of this value, only if we can determine the result precisely. - * The result can be `none()`, but never both `true` and `false`. - */ + /** + * Gets the boolean interpretation of this value, only if we can determine the result precisely. + * The result can be `none()`, but never both `true` and `false`. + */ boolean getDefiniteBooleanValue() { result = getABooleanValue() and not (getABooleanValue() = true and getABooleanValue() = false) } } -/** Class representing modules in the Python program +/** + * Class representing modules in the Python program * Each `ModuleValue` represents a module object in the Python program. */ class ModuleValue extends Value { + ModuleValue() { this instanceof ModuleObjectInternal } - ModuleValue() { - this instanceof ModuleObjectInternal - } - - /** Holds if this module "exports" name. + /** + * Holds if this module "exports" name. * That is, does it define `name` in `__all__` or is * `__all__` not defined and `name` a global variable that does not start with "_" * This is the set of names imported by `from ... import *`. */ - predicate exports(string name) { - PointsTo::moduleExports(this, name) - } + predicate exports(string name) { PointsTo::moduleExports(this, name) } /** Gets the scope for this module, provided that it is a Python module. */ - ModuleScope getScope() { - result = this.(ModuleObjectInternal).getSourceModule() - } + ModuleScope getScope() { result = this.(ModuleObjectInternal).getSourceModule() } - /** Gets the container path for this module. Will be the file for a Python module, + /** + * Gets the container path for this module. Will be the file for a Python module, * the folder for a package and no result for a builtin module. */ Container getPath() { @@ -172,26 +158,20 @@ class ModuleValue extends Value { result = this.(PythonModuleObjectInternal).getSourceModule().getFile() } - /** Whether this module is imported by 'import name'. For example on a linux system, - * the module 'posixpath' is imported as 'os.path' or as 'posixpath' */ - predicate importedAs(string name) { - PointsToInternal::module_imported_as(this, name) - } + /** + * Whether this module is imported by 'import name'. For example on a linux system, + * the module 'posixpath' is imported as 'os.path' or as 'posixpath' + */ + predicate importedAs(string name) { PointsToInternal::module_imported_as(this, name) } /** Whether this module is a package. */ - predicate isPackage() { - this instanceof PackageObjectInternal - } + predicate isPackage() { this instanceof PackageObjectInternal } /** Whether the complete set of names "exported" by this module can be accurately determined */ - predicate hasCompleteExportInfo() { - this.(ModuleObjectInternal).hasCompleteExportInfo() - } + predicate hasCompleteExportInfo() { this.(ModuleObjectInternal).hasCompleteExportInfo() } /** Get a module that this module imports */ - ModuleValue getAnImportedModule() { - result.importedAs(this.getScope().getAnImportedModuleName()) - } + ModuleValue getAnImportedModule() { result.importedAs(this.getScope().getAnImportedModuleName()) } /** When used as a normal module (for example, imported and used by other modules) */ predicate isUsedAsModule() { @@ -214,7 +194,8 @@ class ModuleValue extends Value { i.getScope() = this.getScope() and op instanceof Eq and i.getTest().(Compare).compares(name, op, main) and - name.getId() = "__name__" and main.getText() = "__main__" + name.getId() = "__name__" and + main.getText() = "__main__" ) or exists(Comment c | @@ -227,8 +208,8 @@ class ModuleValue extends Value { } module Module { - - /** Gets the `ModuleValue` named `name`. + /** + * Gets the `ModuleValue` named `name`. * * Note that the name used to refer to a module is not * necessarily its name. For example, @@ -245,25 +226,23 @@ module Module { /* Prevent runaway recursion when a module has itself as an attribute. */ private ModuleValue named(string name, int dots) { - dots = 0 and not name.charAt(_) = "." and + dots = 0 and + not name.charAt(_) = "." and result.getName() = name or dots <= 3 and - exists(string modname, string attrname | - name = modname + "." + attrname | - result = named(modname, dots-1).attr(attrname) + exists(string modname, string attrname | name = modname + "." + attrname | + result = named(modname, dots - 1).attr(attrname) ) } /** Get the `ModuleValue` for the `builtin` module. */ - ModuleValue builtinModule() { - result = TBuiltinModuleObject(Builtin::builtinModule()) - } + ModuleValue builtinModule() { result = TBuiltinModuleObject(Builtin::builtinModule()) } } module Value { - - /** Gets the `Value` named `name`. + /** + * Gets the `Value` named `name`. * If there is at least one '.' in `name`, then the part of * the name to the left of the rightmost '.' is interpreted as a module name * and the part after the rightmost '.' as an attribute of that module. @@ -274,8 +253,7 @@ module Value { * For example `Value::named("len")` is the `Value` representing the `len` built-in function. */ Value named(string name) { - exists(string modname, string attrname | - name = modname + "." + attrname | + exists(string modname, string attrname | name = modname + "." + attrname | result = Module::named(modname).attr(attrname) ) or @@ -288,34 +266,32 @@ module Value { name = "False" and result = TFalse() } - /** Gets the `NumericValue` for the integer constant `i`, if it exists. + /** + * Gets the `NumericValue` for the integer constant `i`, if it exists. * There will be no `NumericValue` for most integers, but the following are * guaranteed to exist: * * From zero to 511 inclusive. * * All powers of 2 (up to 2**30) * * Any integer explicitly mentioned in the source program. */ - NumericValue forInt(int i) { - result.(IntObjectInternal).intValue() = i - } + NumericValue forInt(int i) { result.(IntObjectInternal).intValue() = i } - /** Gets the `Value` for the bytes constant `bytes`, if it exists. + /** + * Gets the `Value` for the bytes constant `bytes`, if it exists. * There will be no `Value` for most byte strings, unless it is explicitly * declared in the source program. */ - StringValue forBytes(string bytes) { - result.(BytesObjectInternal).strValue() = bytes - } + StringValue forBytes(string bytes) { result.(BytesObjectInternal).strValue() = bytes } - /** Gets the `Value` for the unicode constant `text`, if it exists. + /** + * Gets the `Value` for the unicode constant `text`, if it exists. * There will be no `Value` for most text strings, unless it is explicitly * declared in the source program. */ - StringValue forUnicode(string text) { - result.(UnicodeObjectInternal).strValue() = text - } + StringValue forUnicode(string text) { result.(UnicodeObjectInternal).strValue() = text } - /** Gets a `Value` for the string `text`. May be a bytes or unicode string for Python 2. + /** + * Gets a `Value` for the string `text`. May be a bytes or unicode string for Python 2. * There will be no `Value` for most strings, unless it is explicitly * declared in the source program. */ @@ -334,9 +310,7 @@ module Value { } /** Gets the `Value` for `None`. */ - Value none_() { - result = ObjectInternal::none_() - } + Value none_() { result = ObjectInternal::none_() } /** * Shorcuts added by the `site` module to exit your interactive session. @@ -353,32 +327,25 @@ module Value { } } -/** Class representing callables in the Python program +/** + * Class representing callables in the Python program * Callables include Python functions, built-in functions and bound-methods, * but not classes. */ class CallableValue extends Value { + CallableValue() { this instanceof CallableObjectInternal } - CallableValue() { - this instanceof CallableObjectInternal - } - - /** Holds if this callable never returns once called. + /** + * Holds if this callable never returns once called. * For example, `sys.exit` */ - predicate neverReturns() { - this.(CallableObjectInternal).neverReturns() - } + predicate neverReturns() { this.(CallableObjectInternal).neverReturns() } /** Gets the scope for this function, provided that it is a Python function. */ - FunctionScope getScope() { - result = this.(PythonFunctionObjectInternal).getScope() - } + FunctionScope getScope() { result = this.(PythonFunctionObjectInternal).getScope() } /** Gets the `n`th parameter node of this callable. */ - NameNode getParameter(int n) { - result = this.(CallableObjectInternal).getParameter(n) - } + NameNode getParameter(int n) { result = this.(CallableObjectInternal).getParameter(n) } /** Gets the `name`d parameter node of this callable. */ NameNode getParameterByName(string name) { @@ -386,56 +353,60 @@ class CallableValue extends Value { } /** Gets the argument corresponding to the `n'th parameter node of this callable. */ - cached ControlFlowNode getArgumentForCall(CallNode call, int n) { + cached + ControlFlowNode getArgumentForCall(CallNode call, int n) { exists(ObjectInternal called, int offset | PointsToInternal::pointsTo(call.getFunction(), _, called, _) and called.functionAndOffset(this, offset) - | - call.getArg(n-offset) = result + | + call.getArg(n - offset) = result or - exists(string name | call.getArgByName(name) = result and this.(PythonFunctionObjectInternal).getScope().getArg(n+offset).getName() = name) + exists(string name | + call.getArgByName(name) = result and + this.(PythonFunctionObjectInternal).getScope().getArg(n + offset).getName() = name + ) or called instanceof BoundMethodObjectInternal and - offset = 1 and n = 0 and result = call.getFunction().(AttrNode).getObject() + offset = 1 and + n = 0 and + result = call.getFunction().(AttrNode).getObject() ) } - /** Gets the argument corresponding to the `name`d parameter node of this callable. */ - cached ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { + cached + ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { exists(CallableObjectInternal called, int offset | PointsToInternal::pointsTo(call.getFunction(), _, called, _) and called.functionAndOffset(this, offset) - | + | exists(int n | call.getArg(n) = result and - this.(PythonFunctionObjectInternal).getScope().getArg(n+offset).getName() = name + this.(PythonFunctionObjectInternal).getScope().getArg(n + offset).getName() = name ) or call.getArgByName(name) = result and exists(this.(PythonFunctionObjectInternal).getScope().getArgByName(name)) or called instanceof BoundMethodObjectInternal and - offset = 1 and name = "self" and result = call.getFunction().(AttrNode).getObject() + offset = 1 and + name = "self" and + result = call.getFunction().(AttrNode).getObject() ) } - } -/** Class representing classes in the Python program, both Python and built-in. +/** + * Class representing classes in the Python program, both Python and built-in. */ class ClassValue extends Value { - - ClassValue() { - this.(ObjectInternal).isClass() = true - } + ClassValue() { this.(ObjectInternal).isClass() = true } /** Gets an improper super type of this class. */ - ClassValue getASuperType() { - result = this.getABaseType*() - } + ClassValue getASuperType() { result = this.getABaseType*() } - /** Looks up the attribute `name` on this class. + /** + * Looks up the attribute `name` on this class. * Note that this may be different from `this.attr(name)`. * For example given the class: * ```class C: @@ -444,15 +415,11 @@ class ClassValue extends Value { * ``` * `this.lookup("f")` is equivalent to `C.__dict__['f']`, which is the class-method * whereas - * `this.attr("f") is equivalent to `C.f`, which is a bound-method. + * `this.attr("f")` is equivalent to `C.f`, which is a bound-method. */ - Value lookup(string name) { - this.(ClassObjectInternal).lookup(name, result, _) - } + Value lookup(string name) { this.(ClassObjectInternal).lookup(name, result, _) } - predicate isCallable() { - this.(ClassObjectInternal).lookup("__call__", _, _) - } + predicate isCallable() { this.(ClassObjectInternal).lookup("__call__", _, _) } /** Holds if this class is an iterable. */ predicate isIterable() { @@ -462,17 +429,40 @@ class ClassValue extends Value { or this.hasAttribute("__getitem__") } - - /** Holds if this class is a container(). That is, does it have a __getitem__ method.*/ - predicate isContainer() { - exists(this.lookup("__getitem__")) + + /** Holds if this class is an iterator. */ + predicate isIterator() { + this.hasAttribute("__iter__") and + ( + major_version() = 3 and this.hasAttribute("__next__") + or + /* + * Because 'next' is a common method name we need to check that an __iter__ + * method actually returns this class. This is not needed for Py3 as the + * '__next__' method exists to define a class as an iterator. + */ + + major_version() = 2 and + this.hasAttribute("next") and + exists(ClassValue other, FunctionValue iter | other.declaredAttribute("__iter__") = iter | + iter.getAnInferredReturnType() = this + ) + ) + or + /* This will be redundant when we have C class information */ + this = ClassValue::generator() } - + + /** Holds if this class is a container(). That is, does it have a __getitem__ method. */ + predicate isContainer() { exists(this.lookup("__getitem__")) } + /** Holds if this class is probably a sequence. */ predicate isSequence() { - /* To determine whether something is a sequence or a mapping is not entirely clear, + /* + * To determine whether something is a sequence or a mapping is not entirely clear, * so we need to guess a bit. */ + this.getASuperType() = ClassValue::tuple() or this.getASuperType() = ClassValue::list() @@ -494,18 +484,15 @@ class ClassValue extends Value { this.hasAttribute("__reversed__") ) } - + /** Holds if this class is a mapping. */ predicate isMapping() { - this.hasAttribute("__getitem__") - and + this.hasAttribute("__getitem__") and not this.isSequence() } /** Holds if this class is a descriptor. */ - predicate isDescriptorType() { - this.hasAttribute("__get__") - } + predicate isDescriptorType() { this.hasAttribute("__get__") } /** Holds if this class is a context manager. */ predicate isContextManager() { @@ -513,7 +500,8 @@ class ClassValue extends Value { this.hasAttribute("__exit__") } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -523,62 +511,52 @@ class ClassValue extends Value { } /** Gets the MRO for this class */ - MRO getMro() { - result = Types::getMro(this) - } + MRO getMro() { result = Types::getMro(this) } - predicate failedInference(string reason) { - Types::failedInference(this, reason) - } + predicate failedInference(string reason) { Types::failedInference(this, reason) } /** Gets the nth immediate base type of this class. */ - ClassValue getBaseType(int n) { - result = Types::getBase(this, n) - } + ClassValue getBaseType(int n) { result = Types::getBase(this, n) } /** Gets an immediate base type of this class. */ - ClassValue getABaseType() { - result = Types::getBase(this, _) - } + ClassValue getABaseType() { result = Types::getBase(this, _) } - /** Holds if this class is a new style class. - * A new style class is one that implicitly or explicitly inherits from `object`. */ - predicate isNewStyle() { - Types::isNewStyle(this) - } + /** + * Holds if this class is a new style class. + * A new style class is one that implicitly or explicitly inherits from `object`. + */ + predicate isNewStyle() { Types::isNewStyle(this) } - /** Holds if this class is an old style class. - * An old style class is one that does not inherit from `object`. */ - predicate isOldStyle() { - Types::isOldStyle(this) - } + /** + * Holds if this class is an old style class. + * An old style class is one that does not inherit from `object`. + */ + predicate isOldStyle() { Types::isOldStyle(this) } /** Gets the scope associated with this class, if it is not a builtin class */ - ClassScope getScope() { - result = this.(PythonClassObjectInternal).getScope() - } + ClassScope getScope() { result = this.(PythonClassObjectInternal).getScope() } /** Gets the attribute declared in this class */ - Value declaredAttribute(string name) { - Types::declaredAttribute(this, name, result, _) - } + Value declaredAttribute(string name) { Types::declaredAttribute(this, name, result, _) } - /** Holds if this class has the attribute `name`, including - * attributes declared by super classes. + /** + * Holds if this class has the attribute `name`, including attributes + * declared by super classes. */ - predicate hasAttribute(string name) { - this.getMro().declares(name) - } + override predicate hasAttribute(string name) { this.getMro().declares(name) } - /** Holds if this class declares the attribute `name`, + /** + * Holds if this class declares the attribute `name`, * *not* including attributes declared by super classes. */ predicate declaresAttribute(string name) { this.(ClassObjectInternal).getClassDeclaration().declaresAttribute(name) } - /** Whether this class is a legal exception class. - * What constitutes a legal exception class differs between major versions */ + /** + * Whether this class is a legal exception class. + * What constitutes a legal exception class differs between major versions + */ predicate isLegalExceptionType() { not this.isNewStyle() or @@ -586,30 +564,27 @@ class ClassValue extends Value { or major_version() = 2 and this = ClassValue::tuple() } - } - -/** Class representing functions in the Python program, both Python and built-in. +/** + * Class representing functions in the Python program, both Python and built-in. * Note that this does not include other callables such as bound-methods. */ abstract class FunctionValue extends CallableValue { - abstract string getQualifiedName(); + /** Gets a longer, more descriptive version of toString() */ + abstract string descriptiveString(); + /** Gets the minimum number of parameters that can be correctly passed to this function */ abstract int minParameters(); /** Gets the maximum number of parameters that can be correctly passed to this function */ abstract int maxParameters(); - predicate isOverridingMethod() { - exists(Value f | this.overrides(f)) - } + predicate isOverridingMethod() { exists(Value f | this.overrides(f)) } - predicate isOverriddenMethod() { - exists(Value f | f.overrides(this)) - } + predicate isOverriddenMethod() { exists(Value f | f.overrides(this)) } /** Whether `name` is a legal argument name for this function */ bindingset[name] @@ -621,30 +596,47 @@ abstract class FunctionValue extends CallableValue { this.getScope().hasKwArg() } - /** Whether this is a "normal" method, that is, it is exists as a class attribute - * which is not a lambda and not the __new__ method. */ + /** + * Whether this is a "normal" method, that is, it is exists as a class attribute + * which is not a lambda and not the __new__ method. + */ predicate isNormalMethod() { exists(ClassValue cls, string name | cls.declaredAttribute(name) = this and name != "__new__" and - exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | - not origin instanceof Lambda - ) + exists(Expr expr, AstNode origin | expr.pointsTo(this, origin) | not origin instanceof Lambda) ) } + + /** Gets a call-site from where this function is called as a method */ + CallNode getAMethodCall() { + exists(BoundMethodObjectInternal bm | + result.getFunction().pointsTo() = bm and + bm.getFunction() = this + ) + } + + /** Gets a class that this function may return */ + abstract ClassValue getAnInferredReturnType(); } /** Class representing Python functions */ class PythonFunctionValue extends FunctionValue { - - PythonFunctionValue() { - this instanceof PythonFunctionObjectInternal - } + PythonFunctionValue() { this instanceof PythonFunctionObjectInternal } override string getQualifiedName() { result = this.(PythonFunctionObjectInternal).getScope().getQualifiedName() } + override string descriptiveString() { + if this.getScope().isMethod() + then + exists(Class cls | this.getScope().getScope() = cls | + result = "method " + this.getQualifiedName() + ) + else result = "function " + this.getQualifiedName() + } + override int minParameters() { exists(Function f | f = this.getScope() and @@ -655,46 +647,46 @@ class PythonFunctionValue extends FunctionValue { override int maxParameters() { exists(Function f | f = this.getScope() and - if exists(f.getVararg()) then - result = 2147483647 // INT_MAX - else - result = count(f.getAnArg()) + if exists(f.getVararg()) + then result = 2147483647 // INT_MAX + else result = count(f.getAnArg()) ) } /** Gets a control flow node corresponding to a return statement in this function */ - ControlFlowNode getAReturnedNode() { - result = this.getScope().getAReturnValueFlowNode() - } + ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() } + override ClassValue getAnInferredReturnType() { + /* We have to do a special version of this because builtin functions have no + * explicit return nodes that we can query and get the class of. + */ + result = this.getAReturnedNode().pointsTo().getClass() + } } /** Class representing builtin functions, such as `len` or `print` */ class BuiltinFunctionValue extends FunctionValue { + BuiltinFunctionValue() { this instanceof BuiltinFunctionObjectInternal } - BuiltinFunctionValue() { - this instanceof BuiltinFunctionObjectInternal - } + override string getQualifiedName() { result = this.(BuiltinFunctionObjectInternal).getName() } - override string getQualifiedName() { - result = this.(BuiltinFunctionObjectInternal).getName() - } + override string descriptiveString() { result = "builtin-function " + this.getName() } - override int minParameters() { - none() - } + override int minParameters() { none() } - override int maxParameters() { - none() + override int maxParameters() { none() } + + override ClassValue getAnInferredReturnType() { + /* We have to do a special version of this because builtin functions have no + * explicit return nodes that we can query and get the class of. + */ + result = TBuiltinClassObject(this.(BuiltinFunctionObjectInternal).getReturnType()) } } /** Class representing builtin methods, such as `list.append` or `set.add` */ class BuiltinMethodValue extends FunctionValue { - - BuiltinMethodValue() { - this instanceof BuiltinMethodObjectInternal - } + BuiltinMethodValue() { this instanceof BuiltinMethodObjectInternal } override string getQualifiedName() { exists(Builtin cls | @@ -704,46 +696,37 @@ class BuiltinMethodValue extends FunctionValue { ) } - override int minParameters() { - none() - } + override string descriptiveString() { result = "builtin-method " + this.getQualifiedName() } - override int maxParameters() { - none() - } + override int minParameters() { none() } + override int maxParameters() { none() } + + override ClassValue getAnInferredReturnType() { + result = TBuiltinClassObject(this.(BuiltinMethodObjectInternal).getReturnType()) + } } -/** A class representing sequence objects with a length and tracked items. +/** + * A class representing sequence objects with a length and tracked items. */ class SequenceValue extends Value { + SequenceValue() { this instanceof SequenceObjectInternal } - SequenceValue() { - this instanceof SequenceObjectInternal - } - - Value getItem(int n) { - result = this.(SequenceObjectInternal).getItem(n) - } - - int length() { - result = this.(SequenceObjectInternal).length() - } + Value getItem(int n) { result = this.(SequenceObjectInternal).getItem(n) } + int length() { result = this.(SequenceObjectInternal).length() } } /** A class representing tuple objects */ class TupleValue extends SequenceValue { - - TupleValue() { - this instanceof TupleObjectInternal - } - + TupleValue() { this instanceof TupleObjectInternal } } -/** A class representing strings, either present in the source as a literal, or - * in a builtin as a value. */ - +/** + * A class representing strings, either present in the source as a literal, or + * in a builtin as a value. + */ class StringValue extends Value { StringValue() { this instanceof BytesObjectInternal or @@ -757,7 +740,8 @@ class StringValue extends Value { } } -/** A class representing numbers (ints and floats), either present in the source as a literal, +/** + * A class representing numbers (ints and floats), either present in the source as a literal, * or in a builtin as a value. */ class NumericValue extends Value { @@ -767,102 +751,66 @@ class NumericValue extends Value { } /** Gets the integer-value if it is a constant integer, and it fits in a QL int */ - int getIntValue() { - result = this.(IntObjectInternal).intValue() - } + int getIntValue() { result = this.(IntObjectInternal).intValue() } /** Gets the float-value if it is a constant float */ - int getFloatValue() { - result = this.(FloatObjectInternal).floatValue() - } + int getFloatValue() { result = this.(FloatObjectInternal).floatValue() } } -/** A Python property: - * @property - * def f(): +/** + * A Python property: + * + * @property def f(): * .... * * https://docs.python.org/3/howto/descriptor.html#properties * https://docs.python.org/3/library/functions.html#property */ class PropertyValue extends Value { + PropertyValue() { this instanceof PropertyInternal } - PropertyValue() { - this instanceof PropertyInternal - } + CallableValue getGetter() { result = this.(PropertyInternal).getGetter() } - CallableValue getGetter(){ - result = this.(PropertyInternal).getGetter() - } - - CallableValue getSetter(){ - result = this.(PropertyInternal).getSetter() - } - - CallableValue getDeleter(){ - result = this.(PropertyInternal).getDeleter() - } + CallableValue getSetter() { result = this.(PropertyInternal).getSetter() } + CallableValue getDeleter() { result = this.(PropertyInternal).getDeleter() } } /** A method-resolution-order sequence of classes */ class MRO extends TClassList { - - string toString() { - result = this.(ClassList).toString() - } + string toString() { result = this.(ClassList).toString() } /** Gets the `n`th class in this MRO */ - ClassValue getItem(int n) { - result = this.(ClassList).getItem(n) - } + ClassValue getItem(int n) { result = this.(ClassList).getItem(n) } /** Holds if any class in this MRO declares the attribute `name` */ - predicate declares(string name) { - this.(ClassList).declares(name) - } + predicate declares(string name) { this.(ClassList).declares(name) } /** Gets the length of this MRO */ - int length() { - result = this.(ClassList).length() - } + int length() { result = this.(ClassList).length() } /** Holds if this MRO contains `cls` */ - predicate contains(ClassValue cls) { - this.(ClassList).contains(cls) - } + predicate contains(ClassValue cls) { this.(ClassList).contains(cls) } /** Gets the value from scanning for the attribute `name` in this MRO. */ - Value lookup(string name) { - this.(ClassList).lookup(name, result, _) - } + Value lookup(string name) { this.(ClassList).lookup(name, result, _) } - /** Gets the MRO formed by removing all classes before `cls` + /** + * Gets the MRO formed by removing all classes before `cls` * from this MRO. */ - MRO startingAt(ClassValue cls) { - result = this.(ClassList).startingAt(cls) - } - + MRO startingAt(ClassValue cls) { result = this.(ClassList).startingAt(cls) } } - module ClassValue { - /** Get the `ClassValue` for the `bool` class. */ - ClassValue bool() { - result = TBuiltinClassObject(Builtin::special("bool")) - } + ClassValue bool() { result = TBuiltinClassObject(Builtin::special("bool")) } /** Get the `ClassValue` for the `tuple` class. */ - ClassValue tuple() { - result = TBuiltinClassObject(Builtin::special("tuple")) - } + ClassValue tuple() { result = TBuiltinClassObject(Builtin::special("tuple")) } /** Get the `ClassValue` for the `list` class. */ - ClassValue list() { - result = TBuiltinClassObject(Builtin::special("list")) - } + ClassValue list() { result = TBuiltinClassObject(Builtin::special("list")) } /** Get the `ClassValue` for `xrange` (Python 2), or `range` (only Python 3) */ ClassValue range() { @@ -872,115 +820,74 @@ module ClassValue { } /** Get the `ClassValue` for the `dict` class. */ - ClassValue dict() { - result = TBuiltinClassObject(Builtin::special("dict")) - } + ClassValue dict() { result = TBuiltinClassObject(Builtin::special("dict")) } /** Get the `ClassValue` for the `set` class. */ - ClassValue set() { - result = TBuiltinClassObject(Builtin::special("set")) - } + ClassValue set() { result = TBuiltinClassObject(Builtin::special("set")) } /** Get the `ClassValue` for the `object` class. */ - ClassValue object() { - result = TBuiltinClassObject(Builtin::special("object")) - } + ClassValue object() { result = TBuiltinClassObject(Builtin::special("object")) } /** Get the `ClassValue` for the `int` class. */ - ClassValue int_() { - result = TBuiltinClassObject(Builtin::special("int")) - } + ClassValue int_() { result = TBuiltinClassObject(Builtin::special("int")) } /** Get the `ClassValue` for the `long` class. */ - ClassValue long() { - result = TBuiltinClassObject(Builtin::special("long")) - } + ClassValue long() { result = TBuiltinClassObject(Builtin::special("long")) } /** Get the `ClassValue` for the `float` class. */ - ClassValue float_() { - result = TBuiltinClassObject(Builtin::special("float")) - } + ClassValue float_() { result = TBuiltinClassObject(Builtin::special("float")) } /** Get the `ClassValue` for the `complex` class. */ - ClassValue complex() { - result = TBuiltinClassObject(Builtin::special("complex")) - } - + ClassValue complex() { result = TBuiltinClassObject(Builtin::special("complex")) } + /** Get the `ClassValue` for the `bytes` class (also called `str` in Python 2). */ - ClassValue bytes() { - result = TBuiltinClassObject(Builtin::special("bytes")) - } + ClassValue bytes() { result = TBuiltinClassObject(Builtin::special("bytes")) } - /** Get the `ClassValue` for the class of unicode strings. - * `str` in Python 3 and `unicode` in Python 2. */ - ClassValue unicode() { - result = TBuiltinClassObject(Builtin::special("unicode")) - } + /** + * Get the `ClassValue` for the class of unicode strings. + * `str` in Python 3 and `unicode` in Python 2. + */ + ClassValue unicode() { result = TBuiltinClassObject(Builtin::special("unicode")) } - /** Get the `ClassValue` for the `str` class. This is `bytes` in Python 2, - * and `str` in Python 3. */ - ClassValue str() { - if major_version() = 2 then - result = bytes() - else - result = unicode() - } + /** + * Get the `ClassValue` for the `str` class. This is `bytes` in Python 2, + * and `str` in Python 3. + */ + ClassValue str() { if major_version() = 2 then result = bytes() else result = unicode() } /** Get the `ClassValue` for the `property` class. */ - ClassValue property() { - result = TBuiltinClassObject(Builtin::special("property")) - } + ClassValue property() { result = TBuiltinClassObject(Builtin::special("property")) } /** Get the `ClassValue` for the class of Python functions. */ - ClassValue functionType() { - result = TBuiltinClassObject(Builtin::special("FunctionType")) - } + ClassValue functionType() { result = TBuiltinClassObject(Builtin::special("FunctionType")) } /** Get the `ClassValue` for the class of builtin functions. */ - ClassValue builtinFunction() { - result = Value::named("len").getClass() - } + ClassValue builtinFunction() { result = Value::named("len").getClass() } /** Get the `ClassValue` for the `generatorType` class. */ - ClassValue generator() { - result = TBuiltinClassObject(Builtin::special("generator")) - } + ClassValue generator() { result = TBuiltinClassObject(Builtin::special("generator")) } /** Get the `ClassValue` for the `type` class. */ - ClassValue type() { - result = TType() - } + ClassValue type() { result = TType() } /** Get the `ClassValue` for `ClassType`. */ - ClassValue classType() { - result = TBuiltinClassObject(Builtin::special("ClassType")) - } + ClassValue classType() { result = TBuiltinClassObject(Builtin::special("ClassType")) } /** Get the `ClassValue` for `InstanceType`. */ - ClassValue instanceType() { - result = TBuiltinClassObject(Builtin::special("InstanceType")) - } + ClassValue instanceType() { result = TBuiltinClassObject(Builtin::special("InstanceType")) } /** Get the `ClassValue` for `super`. */ - ClassValue super_() { - result = TBuiltinClassObject(Builtin::special("super")) - } + ClassValue super_() { result = TBuiltinClassObject(Builtin::special("super")) } /** Get the `ClassValue` for the `classmethod` class. */ - ClassValue classmethod() { - result = TBuiltinClassObject(Builtin::special("ClassMethod")) - } + ClassValue classmethod() { result = TBuiltinClassObject(Builtin::special("ClassMethod")) } /** Get the `ClassValue` for the `staticmethod` class. */ - ClassValue staticmethod() { - result = TBuiltinClassObject(Builtin::special("StaticMethod")) - } + ClassValue staticmethod() { result = TBuiltinClassObject(Builtin::special("StaticMethod")) } /** Get the `ClassValue` for the `MethodType` class. */ - pragma [noinline] - ClassValue methodType() { - result = TBuiltinClassObject(Builtin::special("MethodType")) - } + pragma[noinline] + ClassValue methodType() { result = TBuiltinClassObject(Builtin::special("MethodType")) } /** Get the `ClassValue` for the `MethodDescriptorType` class. */ ClassValue methodDescriptorType() { @@ -993,59 +900,37 @@ module ClassValue { } /** Get the `ClassValue` for the `StopIteration` class. */ - ClassValue stopIteration() { - result = TBuiltinClassObject(Builtin::builtin("StopIteration")) - } + ClassValue stopIteration() { result = TBuiltinClassObject(Builtin::builtin("StopIteration")) } /** Get the `ClassValue` for the class of modules. */ - ClassValue module_() { - result = TBuiltinClassObject(Builtin::special("ModuleType")) - } + ClassValue module_() { result = TBuiltinClassObject(Builtin::special("ModuleType")) } /** Get the `ClassValue` for the `Exception` class. */ - ClassValue exception() { - result = TBuiltinClassObject(Builtin::special("Exception")) - } + ClassValue exception() { result = TBuiltinClassObject(Builtin::special("Exception")) } /** Get the `ClassValue` for the `BaseException` class. */ - ClassValue baseException() { - result = TBuiltinClassObject(Builtin::special("BaseException")) - } + ClassValue baseException() { result = TBuiltinClassObject(Builtin::special("BaseException")) } /** Get the `ClassValue` for the `NoneType` class. */ - ClassValue nonetype() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + ClassValue nonetype() { result = TBuiltinClassObject(Builtin::special("NoneType")) } /** Get the `ClassValue` for the `TypeError` class */ - ClassValue typeError() { - result = TBuiltinClassObject(Builtin::special("TypeError")) - } + ClassValue typeError() { result = TBuiltinClassObject(Builtin::special("TypeError")) } /** Get the `ClassValue` for the `NameError` class. */ - ClassValue nameError() { - result = TBuiltinClassObject(Builtin::builtin("NameError")) - } + ClassValue nameError() { result = TBuiltinClassObject(Builtin::builtin("NameError")) } /** Get the `ClassValue` for the `AttributeError` class. */ - ClassValue attributeError() { - result = TBuiltinClassObject(Builtin::builtin("AttributeError")) - } + ClassValue attributeError() { result = TBuiltinClassObject(Builtin::builtin("AttributeError")) } /** Get the `ClassValue` for the `KeyError` class. */ - ClassValue keyError() { - result = TBuiltinClassObject(Builtin::builtin("KeyError")) - } + ClassValue keyError() { result = TBuiltinClassObject(Builtin::builtin("KeyError")) } /** Get the `ClassValue` for the `LookupError` class. */ - ClassValue lookupError() { - result = TBuiltinClassObject(Builtin::builtin("LookupError")) - } + ClassValue lookupError() { result = TBuiltinClassObject(Builtin::builtin("LookupError")) } /** Get the `ClassValue` for the `IOError` class. */ - ClassValue ioError() { - result = TBuiltinClassObject(Builtin::builtin("IOError")) - } + ClassValue ioError() { result = TBuiltinClassObject(Builtin::builtin("IOError")) } /** Get the `ClassValue` for the `NotImplementedError` class. */ ClassValue notImplementedError() { @@ -1053,9 +938,7 @@ module ClassValue { } /** Get the `ClassValue` for the `ImportError` class. */ - ClassValue importError() { - result = TBuiltinClassObject(Builtin::builtin("ImportError")) - } + ClassValue importError() { result = TBuiltinClassObject(Builtin::builtin("ImportError")) } /** Get the `ClassValue` for the `UnicodeEncodeError` class. */ ClassValue unicodeEncodeError() { @@ -1066,5 +949,4 @@ module ClassValue { ClassValue unicodeDecodeError() { result = TBuiltinClassObject(Builtin::builtin("UnicodeDecodeError")) } - } diff --git a/python/ql/src/semmle/python/objects/ObjectInternal.qll b/python/ql/src/semmle/python/objects/ObjectInternal.qll index 09f6e883ae1..de4e5b80b54 100644 --- a/python/ql/src/semmle/python/objects/ObjectInternal.qll +++ b/python/ql/src/semmle/python/objects/ObjectInternal.qll @@ -16,16 +16,17 @@ import semmle.python.objects.Constants import semmle.python.objects.Sequences import semmle.python.objects.Descriptors - class ObjectInternal extends TObject { - abstract string toString(); - /** The boolean value of this object, this may be both - * true and false if the "object" represents a set of possible objects. */ + /** + * The boolean value of this object, this may be both + * true and false if the "object" represents a set of possible objects. + */ abstract boolean booleanValue(); - /** Holds if this object is introduced into the code base at `node` given the `context` + /** + * Holds if this object is introduced into the code base at `node` given the `context` * This means that `node`, in `context`, points-to this object, but the object has not flowed * there from anywhere else. * Examples: @@ -41,22 +42,25 @@ class ObjectInternal extends TObject { /** True if this "object" is a class. That is, its class inherits from `type` */ abstract boolean isClass(); - /** Gets the class of this object. */ + /** Gets the class of this object. */ abstract ObjectInternal getClass(); - /** True if this "object" can be meaningfully analysed to determine the boolean value of + /** + * True if this "object" can be meaningfully analysed to determine the boolean value of * equality tests on it. * For example, `None` or `int` can be, but `int()` or an unknown string cannot. */ abstract predicate notTestableForEquality(); - /** Gets the `Builtin` for this object, if any. + /** + * Gets the `Builtin` for this object, if any. * Objects (except unknown and undefined values) should attempt to return * exactly one result for either this method or `getOrigin()`. */ abstract Builtin getBuiltin(); - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * object, if it has a meaningful location in the source code. * This method exists primarily for providing backwards compatibility and * locations for source objects. @@ -64,7 +68,8 @@ class ObjectInternal extends TObject { */ abstract ControlFlowNode getOrigin(); - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. * * This is the context-insensitive version. @@ -72,7 +77,8 @@ class ObjectInternal extends TObject { */ abstract predicate callResult(ObjectInternal obj, CfgOrigin origin); - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. * * This is the context-sensitive version. @@ -80,34 +86,36 @@ class ObjectInternal extends TObject { */ abstract predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin); - /** The integer value of things that have integer values and whose integer value is + /** + * The integer value of things that have integer values and whose integer value is * tracked. * That is, some ints, mainly small numbers, and bools. */ abstract int intValue(); - /** The string value of things that have string values. + /** + * The string value of things that have string values. * That is, strings. */ abstract string strValue(); - /** Holds if the function `scope` is called when this object is called and `paramOffset` + /** + * Holds if the function `scope` is called when this object is called and `paramOffset` * is the difference from the parameter position and the argument position. * For a normal function `paramOffset` is 0. For classes and bound-methods it is 1. * Used by points-to to help determine flow from arguments to parameters. */ abstract predicate calleeAndOffset(Function scope, int paramOffset); - final predicate isBuiltin() { - exists(this.getBuiltin()) - } + final predicate isBuiltin() { exists(this.getBuiltin()) } - /** Holds if the result of getting the attribute `name` is `value` and that `value` comes + /** + * Holds if the result of getting the attribute `name` is `value` and that `value` comes * from `origin`. Note this is *not* the same as class lookup. For example - * for an object `x` the attribute `name` (`x.name`) may refer to a bound-method, an attribute of the + * for an object `x` the attribute `name` (`x.name`) may refer to a bound-method, an attribute of the * instance, or an attribute of the class. */ - pragma [nomagic] + pragma[nomagic] abstract predicate attribute(string name, ObjectInternal value, CfgOrigin origin); /** Holds if the attributes of this object are wholly or partly unknowable */ @@ -116,59 +124,71 @@ class ObjectInternal extends TObject { /** Holds if the result of subscripting this object are wholly or partly unknowable */ abstract predicate subscriptUnknown(); - /** For backwards compatibility shim -- Not all objects have a "source". + /** + * For backwards compatibility shim -- Not all objects have a "source". * Objects (except unknown and undefined values) should attempt to return * exactly one result for this method. - * */ + */ @py_object getSource() { result = this.getOrigin() or result = this.getBuiltin() } - /** Holds if this object is a descriptor. + /** + * Holds if this object is a descriptor. * Holds, for example, for functions and properties and not for integers. */ abstract boolean isDescriptor(); - /** Holds if the result of attribute access on the class holding this descriptor is `value`, originating at `origin` + /** + * Holds if the result of attribute access on the class holding this descriptor is `value`, originating at `origin` * For example, although `T.__dict__['name'] = classmethod(f)`, `T.name` is a bound-method, binding `f` and `T` */ pragma[nomagic] abstract predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin); - /** Holds if the result of attribute access on an instance of a class holding this descriptor is `value`, originating at `origin` + /** + * Holds if the result of attribute access on an instance of a class holding this descriptor is `value`, originating at `origin` * For example, with `T.__dict__['name'] = classmethod(f)`, `T().name` is a bound-method, binding `f` and `T` */ pragma[nomagic] - abstract predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin); + abstract predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ); - /** Holds if attribute lookup on this object may "bind" `instance` to `descriptor`. + /** + * Holds if attribute lookup on this object may "bind" `instance` to `descriptor`. * Here "bind" means that `instance` is passed to the `descriptor.__get__()` method * at runtime. The term "bind" is used as this most likely results in a bound-method. */ abstract predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor); - /** Gets the length of the sequence that this "object" represents. + /** + * Gets the length of the sequence that this "object" represents. * Always returns a value for a sequence, will be -1 if the object has no fixed length. */ abstract int length(); - /** Holds if the object `function` is called when this object is called and `paramOffset` + /** + * Holds if the object `function` is called when this object is called and `paramOffset` * is the difference from the parameter position and the argument position. * For a normal function `paramOffset` is 0. For classes and bound-methods it is 1. * This is used to implement the `CallableValue` public API. */ predicate functionAndOffset(CallableObjectInternal function, int offset) { none() } - /** Holds if this 'object' represents an entity that should be exposed to the legacy points_to API + /** + * Holds if this 'object' represents an entity that should be exposed to the legacy points_to API * This should hold for almost all objects that do not have an underlying DB object representing their source, * for example `super` objects and bound-method. This should not hold for objects that are inferred to exists by - * an import statements or the like, but which aren't in the database. */ - /* This predicate can be removed when the legacy points_to API is removed. */ + * an import statements or the like, but which aren't in the database. + */ + /* This predicate can be removed when the legacy points_to API is removed. */ abstract predicate useOriginAsLegacyObject(); - /** Gets the name of this of this object if it has a meaningful name. + /** + * Gets the name of this of this object if it has a meaningful name. * Note that the name of an object is not necessarily the name by which it is called * For example the function named `posixpath.join` will be called `os.path.join`. */ @@ -176,50 +196,36 @@ class ObjectInternal extends TObject { abstract predicate contextSensitiveCallee(); - /** Gets the 'object' resulting from iterating over this object. + /** + * Gets the 'object' resulting from iterating over this object. * Used in the context `for i in this:`. The result is the 'object' * assigned to `i`. */ abstract ObjectInternal getIterNext(); /** Holds if this value has the attribute `name` */ - predicate hasAttribute(string name) { - this.(ObjectInternal).attribute(name, _, _) - } + predicate hasAttribute(string name) { this.(ObjectInternal).attribute(name, _, _) } abstract predicate isNotSubscriptedType(); - } - class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { + override Builtin getBuiltin() { this = TBuiltinOpaqueObject(result) } - override Builtin getBuiltin() { - this = TBuiltinOpaqueObject(result) - } - - override string toString() { - result = this.getBuiltin().getClass().getName() + " object" - } + override string toString() { result = this.getBuiltin().getClass().getName() + " object" } override boolean booleanValue() { // TO DO ... Depends on class. `result = this.getClass().instancesBooleanValue()` result = maybe() } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = TBuiltinClassObject(this.getBuiltin().getClass()) - } + override ObjectInternal getClass() { result = TBuiltinClassObject(this.getBuiltin().getClass()) } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } @@ -231,46 +237,47 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { value = ObjectInternal::fromBuiltin(this.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } - override predicate subscriptUnknown() { - exists(this.getBuiltin().getItem(_)) - } + override predicate subscriptUnknown() { exists(this.getBuiltin().getItem(_)) } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } - override string getName() { - result = this.getBuiltin().getName() - } + override string getName() { result = this.getBuiltin().getName() } override predicate contextSensitiveCallee() { none() } @@ -279,39 +286,24 @@ class BuiltinOpaqueObjectInternal extends ObjectInternal, TBuiltinOpaqueObject { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } - class UnknownInternal extends ObjectInternal, TUnknown { + override string toString() { result = "Unknown value" } - override string toString() { - result = "Unknown value" - } + override boolean booleanValue() { result = maybe() } - override boolean booleanValue() { - result = maybe() - } - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } - override ObjectInternal getClass() { - result = TUnknownClass() - } + override ObjectInternal getClass() { result = TUnknownClass() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { any() } - override Builtin getBuiltin() { - result = Builtin::unknown() - } + override Builtin getBuiltin() { result = Builtin::unknown() } override predicate callResult(ObjectInternal obj, CfgOrigin origin) { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() @@ -321,37 +313,40 @@ class UnknownInternal extends ObjectInternal, TUnknown { none() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { any() } + pragma[noinline] + override predicate attributesUnknown() { any() } override predicate subscriptUnknown() { any() } override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { result = -1 } @@ -364,38 +359,24 @@ class UnknownInternal extends ObjectInternal, TUnknown { override ObjectInternal getIterNext() { result = ObjectInternal::unknown() } override predicate isNotSubscriptedType() { any() } - } class UndefinedInternal extends ObjectInternal, TUndefined { + override string toString() { result = "Undefined variable" } - override string toString() { - result = "Undefined variable" - } + override boolean booleanValue() { none() } - override boolean booleanValue() { - none() - } - - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override predicate notTestableForEquality() { any() } - override ObjectInternal getClass() { - none() - } + override ObjectInternal getClass() { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() @@ -407,37 +388,40 @@ class UndefinedInternal extends ObjectInternal, TUndefined { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } override boolean isDescriptor() { none() } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } @@ -445,39 +429,31 @@ class UndefinedInternal extends ObjectInternal, TUndefined { override predicate useOriginAsLegacyObject() { none() } - /** Holds if this object requires context to determine the object resulting from a call to it. - * True for most callables. */ + /** + * Holds if this object requires context to determine the object resulting from a call to it. + * True for most callables. + */ override predicate contextSensitiveCallee() { none() } override ObjectInternal getIterNext() { none() } override predicate isNotSubscriptedType() { any() } - } module ObjectInternal { - ObjectInternal bool(boolean b) { b = true and result = TTrue() or b = false and result = TFalse() } - ObjectInternal none_() { - result = TNone() - } + ObjectInternal none_() { result = TNone() } - ObjectInternal unknown() { - result = TUnknown() - } + ObjectInternal unknown() { result = TUnknown() } - ClassObjectInternal unknownClass() { - result = TUnknownClass() - } + ClassObjectInternal unknownClass() { result = TUnknownClass() } - ObjectInternal undefined() { - result = TUndefined() - } + ObjectInternal undefined() { result = TUndefined() } ObjectInternal builtin(string name) { result = TBuiltinClassObject(Builtin::builtin(name)) @@ -490,12 +466,10 @@ module ObjectInternal { } ObjectInternal sysModules() { - result = TBuiltinOpaqueObject(Builtin::special("sys").getMember("modules")) + result = TBuiltinOpaqueObject(Builtin::special("sys").getMember("modules")) } - ObjectInternal fromInt(int n) { - result = TInt(n) - } + ObjectInternal fromInt(int n) { result = TInt(n) } ObjectInternal fromBuiltin(Builtin b) { b = result.getBuiltin() and @@ -506,67 +480,38 @@ module ObjectInternal { b = Builtin::special("sys").getMember("version_info") and result = TSysVersionInfo() } - ObjectInternal classMethod() { - result = TBuiltinClassObject(Builtin::special("ClassMethod")) - } + ObjectInternal classMethod() { result = TBuiltinClassObject(Builtin::special("ClassMethod")) } - ObjectInternal staticMethod() { - result = TBuiltinClassObject(Builtin::special("StaticMethod")) - } + ObjectInternal staticMethod() { result = TBuiltinClassObject(Builtin::special("StaticMethod")) } - ObjectInternal boundMethod() { - result = TBuiltinClassObject(Builtin::special("MethodType")) - } + ObjectInternal boundMethod() { result = TBuiltinClassObject(Builtin::special("MethodType")) } - ObjectInternal moduleType() { - result = TBuiltinClassObject(Builtin::special("ModuleType")) - } + ObjectInternal moduleType() { result = TBuiltinClassObject(Builtin::special("ModuleType")) } - ObjectInternal noneType() { - result = TBuiltinClassObject(Builtin::special("NoneType")) - } + ObjectInternal noneType() { result = TBuiltinClassObject(Builtin::special("NoneType")) } - ObjectInternal type() { - result = TType() - } + ObjectInternal type() { result = TType() } - ObjectInternal property() { - result = TBuiltinClassObject(Builtin::special("property")) - } + ObjectInternal property() { result = TBuiltinClassObject(Builtin::special("property")) } - ObjectInternal superType() { - result = TBuiltinClassObject(Builtin::special("super")) - } + ObjectInternal superType() { result = TBuiltinClassObject(Builtin::special("super")) } /** The old-style class type (Python 2 only) */ - ObjectInternal classType() { - result = TBuiltinClassObject(Builtin::special("ClassType")) - } - - ObjectInternal emptyTuple() { - result.(BuiltinTupleObjectInternal).length() = 0 - } + ObjectInternal classType() { result = TBuiltinClassObject(Builtin::special("ClassType")) } + ObjectInternal emptyTuple() { result.(BuiltinTupleObjectInternal).length() = 0 } } class DecoratedFunction extends ObjectInternal, TDecoratedFunction { + CallNode getDecoratorCall() { this = TDecoratedFunction(result) } - - CallNode getDecoratorCall() { - this = TDecoratedFunction(result) - } - - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } private ObjectInternal decoratedObject() { PointsTo::pointsTo(this.getDecoratorCall().getArg(0), _, result, _) } - override string getName() { - result = this.decoratedObject().getName() - } + override string getName() { result = this.decoratedObject().getName() } override string toString() { result = "Decorated " + this.decoratedObject().toString() @@ -576,17 +521,13 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override boolean booleanValue() { result = true } - override ClassDecl getClassDeclaration() { - none() - } + override ClassDecl getClassDeclaration() { none() } override boolean isClass() { result = false } override ObjectInternal getClass() { result = TUnknownClass() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } override predicate notTestableForEquality() { none() } @@ -598,25 +539,15 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { obj = ObjectInternal::unknown() and origin = CfgOrigin::unknown() } - override ControlFlowNode getOrigin() { - result = this.getDecoratorCall() - } + override ControlFlowNode getOrigin() { result = this.getDecoratorCall() } - override int intValue() { - none() - } + override int intValue() { none() } - override string strValue() { - none() - } + override string strValue() { none() } - override predicate calleeAndOffset(Function scope, int paramOffset) { - none() - } + override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { - none() - } + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } override predicate attributesUnknown() { none() } @@ -624,11 +555,22 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override int length() { none() } @@ -639,17 +581,13 @@ class DecoratedFunction extends ObjectInternal, TDecoratedFunction { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** Helper for boolean predicates returning both `true` and `false` */ -boolean maybe() { - result = true or result = false -} +boolean maybe() { result = true or result = false } /** Helper for attributes */ -pragma [nomagic] +pragma[nomagic] predicate receiver_type(AttrNode attr, string name, ObjectInternal value, ClassObjectInternal cls) { PointsToInternal::pointsTo(attr.getObject(name), _, value, _) and value.getClass() = cls } - diff --git a/python/ql/src/semmle/python/objects/Sequences.qll b/python/ql/src/semmle/python/objects/Sequences.qll index d6c08315b85..1259aadc07b 100644 --- a/python/ql/src/semmle/python/objects/Sequences.qll +++ b/python/ql/src/semmle/python/objects/Sequences.qll @@ -1,9 +1,4 @@ - import python - - - - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo @@ -12,7 +7,6 @@ private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins abstract class SequenceObjectInternal extends ObjectInternal { - /** Gets the `n`th item of this sequence, if one exists. */ abstract ObjectInternal getItem(int n); @@ -24,45 +18,50 @@ abstract class SequenceObjectInternal extends ObjectInternal { override boolean isDescriptor() { result = false } - pragma [noinline] override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetClass(ObjectInternal cls, ObjectInternal value, CfgOrigin origin) { + none() + } - pragma [noinline] override predicate descriptorGetInstance(ObjectInternal instance, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate descriptorGetInstance( + ObjectInternal instance, ObjectInternal value, CfgOrigin origin + ) { + none() + } - pragma [noinline] override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { none() } + pragma[noinline] + override predicate binds(ObjectInternal instance, string name, ObjectInternal descriptor) { + none() + } override string getName() { none() } override predicate contextSensitiveCallee() { none() } override ObjectInternal getIterNext() { result = this.getItem(_) } - } abstract class TupleObjectInternal extends SequenceObjectInternal { - - override string toString() { - result = "(" + this.contents(0) + ")" - } + override string toString() { result = "(" + this.contents(0) + ")" } private string contents(int n) { n < 4 and n = this.length() and result = "" or - n = 3 and this.length() > 3 and result = (this.length()-3).toString() + " more..." + n = 3 and this.length() > 3 and result = (this.length() - 3).toString() + " more..." or - result = this.item(n) + ", " + this.contents(n+1) + result = this.item(n) + ", " + this.contents(n + 1) } private string item(int n) { exists(ObjectInternal item | item = this.getItem(n) | // To avoid infinite recursion, nested tuples are replaced with the string "...". - if item instanceof TupleObjectInternal then - result = "(...)" - else - result = item.toString() + if item instanceof TupleObjectInternal then result = "(...)" else result = item.toString() ) or - n in [0..this.length()-1] and - not exists(this.getItem(n)) and result = "?" + n in [0 .. this.length() - 1] and + not exists(this.getItem(n)) and + result = "?" } /** Gets the class declaration for this object, if it is a declared class. */ @@ -73,60 +72,59 @@ abstract class TupleObjectInternal extends SequenceObjectInternal { override ObjectInternal getClass() { result = ObjectInternal::builtin("tuple") } - /** True if this "object" can be meaningfully analysed for + /** + * True if this "object" can be meaningfully analysed for * truth or false in comparisons. For example, `None` or `int` can be, but `int()` * or an unknown string cannot. */ override predicate notTestableForEquality() { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. */ override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. */ - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, ints and bools. */ override int intValue() { none() } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, strings. */ override string strValue() { none() } override predicate calleeAndOffset(Function scope, int paramOffset) { none() } - pragma [noinline] override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } + pragma[noinline] + override predicate attribute(string name, ObjectInternal value, CfgOrigin origin) { none() } - pragma [noinline] override predicate attributesUnknown() { none() } + pragma[noinline] + override predicate attributesUnknown() { none() } override predicate subscriptUnknown() { none() } - } /** A tuple built-in to the interpreter, including the empty tuple. */ class BuiltinTupleObjectInternal extends TBuiltinTuple, TupleObjectInternal { + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override Builtin getBuiltin() { this = TBuiltinTuple(result) } - override Builtin getBuiltin() { - this = TBuiltinTuple(result) - } + override ControlFlowNode getOrigin() { none() } - override ControlFlowNode getOrigin() { - none() - } - - override ObjectInternal getItem(int n) { - result.getBuiltin() = this.getBuiltin().getItem(n) - } + override ObjectInternal getItem(int n) { result.getBuiltin() = this.getBuiltin().getItem(n) } override int length() { exists(Builtin b | @@ -138,23 +136,17 @@ class BuiltinTupleObjectInternal extends TBuiltinTuple, TupleObjectInternal { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** A tuple declared by a tuple expression in the Python source code */ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal { - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { this = TPythonTuple(node, context) } - override Builtin getBuiltin() { - none() - } + override Builtin getBuiltin() { none() } - override ControlFlowNode getOrigin() { - this = TPythonTuple(result, _) - } + override ControlFlowNode getOrigin() { this = TPythonTuple(result, _) } override ObjectInternal getItem(int n) { exists(TupleNode t, PointsToContext context | @@ -173,51 +165,37 @@ class PythonTupleObjectInternal extends TPythonTuple, TupleObjectInternal { override predicate useOriginAsLegacyObject() { none() } override predicate isNotSubscriptedType() { any() } - } /** A tuple created by a `*` parameter */ -class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal { +class VarargsTupleObjectInternal extends TVarargsTuple, TupleObjectInternal { + override predicate introducedAt(ControlFlowNode node, PointsToContext context) { none() } - override predicate introducedAt(ControlFlowNode node, PointsToContext context) { - none() - } + override Builtin getBuiltin() { none() } - override Builtin getBuiltin() { - none() - } - - override ControlFlowNode getOrigin() { - none() - } + override ControlFlowNode getOrigin() { none() } override ObjectInternal getItem(int n) { exists(CallNode call, PointsToContext context, int offset, int length | this = TVarargsTuple(call, context, offset, length) and n < length and - InterProceduralPointsTo::positional_argument_points_to(call, offset+n, context, result, _) + InterProceduralPointsTo::positional_argument_points_to(call, offset + n, context, result, _) ) } - override int length() { - this = TVarargsTuple(_, _, _, result) - } + override int length() { this = TVarargsTuple(_, _, _, result) } override predicate useOriginAsLegacyObject() { any() } override predicate isNotSubscriptedType() { any() } - } - -/** The `sys.version_info` object. We treat this specially to prevent premature pruning and +/** + * The `sys.version_info` object. We treat this specially to prevent premature pruning and * false positives when we are unsure of the actual version of Python that the code is expecting. */ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectInternal { - - override string toString() { - result = "sys.version_info" - } + override string toString() { result = "sys.version_info" } override ObjectInternal getItem(int n) { n = 0 and result = TInt(major_version()) @@ -235,39 +213,45 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern /** True if this "object" is a class. */ override boolean isClass() { result = false } - override ObjectInternal getClass() { - result.getBuiltin() = this.getClassDeclaration() - } + override ObjectInternal getClass() { result.getBuiltin() = this.getClassDeclaration() } override predicate notTestableForEquality() { none() } - /** Gets the `Builtin` for this object, if any. + /** + * Gets the `Builtin` for this object, if any. * Objects (except unknown and undefined values) should attempt to return * exactly one result for either this method or `getOrigin()`. */ override Builtin getBuiltin() { none() } - /** Gets a control flow node that represents the source origin of this + /** + * Gets a control flow node that represents the source origin of this * objects. */ override ControlFlowNode getOrigin() { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj`. */ override predicate callResult(ObjectInternal obj, CfgOrigin origin) { none() } - /** Holds if `obj` is the result of calling `this` and `origin` is + /** + * Holds if `obj` is the result of calling `this` and `origin` is * the origin of `obj` with callee context `callee`. */ - override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { none() } + override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) { + none() + } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, ints and bools. */ override int intValue() { none() } - /** The integer value of things that have integer values. + /** + * The integer value of things that have integer values. * That is, strings. */ override string strValue() { none() } @@ -280,7 +264,8 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern override predicate subscriptUnknown() { none() } - /** Gets the length of the sequence that this "object" represents. + /** + * Gets the length of the sequence that this "object" represents. * Always returns a value for a sequence, will be -1 if object has no fixed length. */ override int length() { result = 5 } @@ -290,5 +275,4 @@ class SysVersionInfoObjectInternal extends TSysVersionInfo, SequenceObjectIntern override predicate useOriginAsLegacyObject() { any() } override predicate isNotSubscriptedType() { any() } - } diff --git a/python/ql/src/semmle/python/objects/TObject.qll b/python/ql/src/semmle/python/objects/TObject.qll index 48cd8784dae..15035bf722a 100644 --- a/python/ql/src/semmle/python/objects/TObject.qll +++ b/python/ql/src/semmle/python/objects/TObject.qll @@ -4,239 +4,193 @@ private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext -/** Internal type backing `ObjectInternal` and `Value` +/** + * Internal type backing `ObjectInternal` and `Value` * See `ObjectInternal.qll` for an explanation of the API. */ -cached newtype TObject = +cached +newtype TObject = /* Builtin class objects */ TBuiltinClassObject(Builtin bltn) { bltn.isClass() and not bltn = Builtin::unknownType() and not bltn = Builtin::special("type") - } - or + } or /* Builtin function objects (module members) */ - TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() } - or + TBuiltinFunctionObject(Builtin bltn) { bltn.isFunction() } or /* Builtin method objects (class members) */ - TBuiltinMethodObject(Builtin bltn) { bltn.isMethod() } - or + TBuiltinMethodObject(Builtin bltn) { bltn.isMethod() } or /* Builtin module objects */ - TBuiltinModuleObject(Builtin bltn) { bltn.isModule() } - or + TBuiltinModuleObject(Builtin bltn) { bltn.isModule() } or /* Other builtin objects from the interpreter */ TBuiltinOpaqueObject(Builtin bltn) { - not bltn.isClass() and not bltn.isFunction() and - not bltn.isMethod() and not bltn.isModule() and + not bltn.isClass() and + not bltn.isFunction() and + not bltn.isMethod() and + not bltn.isModule() and not bltn.getClass() = Builtin::special("tuple") and not exists(bltn.intValue()) and not exists(bltn.floatValue()) and not exists(bltn.strValue()) and not py_special_objects(bltn, _) - } - or + } or /* Python function objects (including lambdas) */ - TPythonFunctionObject(ControlFlowNode callable) { - callable.getNode() instanceof CallableExpr - } - or + TPythonFunctionObject(ControlFlowNode callable) { callable.getNode() instanceof CallableExpr } or /* Python class objects */ - TPythonClassObject(ControlFlowNode classexpr) { - classexpr.getNode() instanceof ClassExpr - } - or + TPythonClassObject(ControlFlowNode classexpr) { classexpr.getNode() instanceof ClassExpr } or /* Package objects */ - TPackageObject(Folder f) { - isPreferredModuleForName(f, _) - } - or + TPackageObject(Folder f) { isPreferredModuleForName(f, _) } or /* Python module objects */ TPythonModule(Module m) { - not m.isPackage() and isPreferredModuleForName(m.getFile(), _) and + not m.isPackage() and + isPreferredModuleForName(m.getFile(), _) and not exists(SyntaxError se | se.getFile() = m.getFile()) - } - or + } or /* `True` */ - TTrue() - or + TTrue() or /* `False` */ - TFalse() - or + TFalse() or /* `None` */ - TNone() - or + TNone() or /* Represents any value about which nothing useful is known */ - TUnknown() - or + TUnknown() or /* Represents any value known to be a class, but not known to be any specific class */ - TUnknownClass() - or + TUnknownClass() or /* Represents the absence of a value. Used by points-to for tracking undefined variables */ - TUndefined() - or + TUndefined() or /* The integer `n` */ TInt(int n) { // Powers of 2 are used for flags - is_power_2(n) or + is_power_2(n) + or // And all combinations of flags up to 2^8 - n in [0..511] or + n in [0 .. 511] + or // Any number explicitly mentioned in the source code. exists(IntegerLiteral num | - n = num.getValue() or - exists(UnaryExpr neg | neg.getOp() instanceof USub and neg.getOperand() = num) - and n = -num.getN().toInt() + n = num.getValue() + or + exists(UnaryExpr neg | neg.getOp() instanceof USub and neg.getOperand() = num) and + n = -num.getN().toInt() ) or n = any(Builtin b).intValue() - } - or + } or /* The float `f` */ - TFloat(float f) { - f = any(FloatLiteral num).getValue() - } - or + TFloat(float f) { f = any(FloatLiteral num).getValue() } or /* The unicode string `s` */ TUnicode(string s) { // Any string explicitly mentioned in the source code. - exists(StrConst str | + exists(StrConst str | s = str.getText() and str.isUnicode() ) or // Any string from the library put in the DB by the extractor. exists(Builtin b | - s = b.strValue() and + s = b.strValue() and b.getClass() = Builtin::special("unicode") ) or s = "__main__" - } - or + } or /* The byte string `s` */ TBytes(string s) { // Any string explicitly mentioned in the source code. - exists(StrConst str | + exists(StrConst str | s = str.getText() and not str.isUnicode() ) or // Any string from the library put in the DB by the extractor. exists(Builtin b | - s = b.strValue() and + s = b.strValue() and b.getClass() = Builtin::special("bytes") ) or s = "__main__" - } - or + } or /* An instance of `cls`, instantiated at `instantiation` given the `context`. */ TSpecificInstance(ControlFlowNode instantiation, ClassObjectInternal cls, PointsToContext context) { PointsToInternal::pointsTo(instantiation.(CallNode).getFunction(), context, cls, _) and cls.isSpecial() = false or literal_instantiation(instantiation, cls, context) - } - or + } or /* A non-specific instance `cls` which enters the scope at `def` given the callee `context`. */ TSelfInstance(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) { self_parameter(def, context, cls) - } - or + } or /* A bound method */ TBoundMethod(ObjectInternal self, CallableObjectInternal function) { any(ObjectInternal obj).binds(self, _, function) and function.isDescriptor() = true - } - or + } or /* Represents any value whose class is known, but nothing else */ TUnknownInstance(BuiltinClassObjectInternal cls) { cls != ObjectInternal::superType() and cls != ObjectInternal::builtin("bool") and cls != ObjectInternal::noneType() - } - or + } or /* Represents an instance of `super` */ TSuperInstance(ObjectInternal self, ClassObjectInternal startclass) { super_instantiation(_, self, startclass, _) - } - or + } or /* Represents an instance of `classmethod` */ TClassMethod(CallNode instantiation, CallableObjectInternal function) { class_method(instantiation, function, _) - } - or + } or /* Represents an instance of `staticmethod` */ TStaticMethod(CallNode instantiation, CallableObjectInternal function) { static_method(instantiation, function, _) - } - or + } or /* Represents a builtin tuple */ - TBuiltinTuple(Builtin bltn) { - bltn.getClass() = Builtin::special("tuple") - } - or + TBuiltinTuple(Builtin bltn) { bltn.getClass() = Builtin::special("tuple") } or /* Represents a tuple in the Python source */ TPythonTuple(TupleNode origin, PointsToContext context) { origin.isLoad() and context.appliesTo(origin) - } - or + } or /* Varargs tuple */ TVarargsTuple(CallNode call, PointsToContext context, int offset, int length) { InterProceduralPointsTo::varargs_tuple(call, context, _, _, offset, length) - } - or + } or /* `type` */ - TType() - or + TType() or /* Represents an instance of `property` */ TProperty(CallNode call, Context ctx, CallableObjectInternal getter) { PointsToInternal::pointsTo(call.getFunction(), ctx, ObjectInternal::property(), _) and PointsToInternal::pointsTo(call.getArg(0), ctx, getter, _) - } - or + } or /* Represents the `setter` or `deleter` method of a property object. */ TPropertySetterOrDeleter(PropertyInternal property, string method) { - exists(AttrNode attr | - PointsToInternal::pointsTo(attr.getObject(method), _, property, _) - ) and - ( method = "setter" or method = "deleter" ) - } - or + exists(AttrNode attr | PointsToInternal::pointsTo(attr.getObject(method), _, property, _)) and + (method = "setter" or method = "deleter") + } or /* Represents a dynamically created class */ TDynamicClass(CallNode instantiation, ClassObjectInternal metacls, PointsToContext context) { PointsToInternal::pointsTo(instantiation.getFunction(), context, metacls, _) and not count(instantiation.getAnArg()) = 1 and Types::getMro(metacls).contains(TType()) - } - or + } or /* Represents `sys.version_info`. Acts like a tuple with a range of values depending on the version being analysed. */ - TSysVersionInfo() - or + TSysVersionInfo() or /* Represents a module that is inferred to perhaps exist, but is not present in the database. */ - TAbsentModule(string name) { - missing_imported_module(_, _, name) - } - or + TAbsentModule(string name) { missing_imported_module(_, _, name) } or /* Represents an attribute of a module that is inferred to perhaps exist, but is not present in the database. */ TAbsentModuleAttribute(AbsentModuleObjectInternal mod, string attrname) { ( PointsToInternal::pointsTo(any(AttrNode attr).getObject(attrname), _, mod, _) or PointsToInternal::pointsTo(any(ImportMemberNode imp).getModule(attrname), _, mod, _) - ) - and + ) and exists(string modname | modname = mod.getName() and not common_module_name(modname + "." + attrname) ) - } - or + } or /* Opaque object representing the result of calling a decorator on a function that we don't understand */ - TDecoratedFunction(CallNode call) { - call.isFunctionDecoratorCall() - } - or + TDecoratedFunction(CallNode call) { call.isFunctionDecoratorCall() } or /* Represents a subscript operation applied to a type. For type-hint analysis */ TSubscriptedType(ObjectInternal generic, ObjectInternal index) { isType(generic) and @@ -252,16 +206,22 @@ predicate isType(ObjectInternal t) { } private predicate is_power_2(int n) { - n = 1 or - exists(int half | is_power_2(half) and n = half*2) + n = 1 + or + exists(int half | is_power_2(half) and n = half * 2) } -predicate static_method(CallNode instantiation, CallableObjectInternal function, PointsToContext context) { - PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("staticmethod"), _) and +predicate static_method( + CallNode instantiation, CallableObjectInternal function, PointsToContext context +) { + PointsToInternal::pointsTo(instantiation.getFunction(), context, + ObjectInternal::builtin("staticmethod"), _) and PointsToInternal::pointsTo(instantiation.getArg(0), context, function, _) } -predicate class_method(CallNode instantiation, CallableObjectInternal function, PointsToContext context) { +predicate class_method( + CallNode instantiation, CallableObjectInternal function, PointsToContext context +) { PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::classMethod(), _) and PointsToInternal::pointsTo(instantiation.getArg(0), context, function, _) } @@ -285,14 +245,20 @@ predicate literal_instantiation(ControlFlowNode n, ClassObjectInternal cls, Poin ) } -predicate super_instantiation(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { +predicate super_instantiation( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { super_2args(instantiation, self, startclass, context) or super_noargs(instantiation, self, startclass, context) } -pragma [noinline] -private predicate super_2args(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { +pragma[noinline] +private predicate super_2args( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { exists(ControlFlowNode arg0, ControlFlowNode arg1 | super_call2(instantiation, arg0, arg1, context) and PointsToInternal::pointsTo(arg0, context, startclass, _) and @@ -300,17 +266,23 @@ private predicate super_2args(CallNode instantiation, ObjectInternal self, Class ) } -pragma [noinline] -private predicate super_call2(CallNode call, ControlFlowNode arg0, ControlFlowNode arg1, PointsToContext context) { +pragma[noinline] +private predicate super_call2( + CallNode call, ControlFlowNode arg0, ControlFlowNode arg1, PointsToContext context +) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::superType(), _) ) } -pragma [noinline] -private predicate super_noargs(CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, PointsToContext context) { - PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("super"), _) and +pragma[noinline] +private predicate super_noargs( + CallNode instantiation, ObjectInternal self, ClassObjectInternal startclass, + PointsToContext context +) { + PointsToInternal::pointsTo(instantiation.getFunction(), context, ObjectInternal::builtin("super"), + _) and not exists(instantiation.getArg(0)) and exists(Function func | instantiation.getScope() = func and @@ -328,7 +300,10 @@ predicate call2(CallNode call, ControlFlowNode func, ControlFlowNode arg0, Contr arg1 = call.getArg(1) } -predicate call3(CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) { +predicate call3( + CallNode call, ControlFlowNode func, ControlFlowNode arg0, ControlFlowNode arg1, + ControlFlowNode arg2 +) { not exists(call.getArg(3)) and func = call.getFunction() and arg0 = call.getArg(0) and @@ -337,9 +312,11 @@ predicate call3(CallNode call, ControlFlowNode func, ControlFlowNode arg0, Contr } bindingset[self, function] -predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, PointsToContext context) { - exists(ObjectInternal obj, string name | - receiver(instantiation, context, obj, name) | +predicate method_binding( + AttrNode instantiation, ObjectInternal self, CallableObjectInternal function, + PointsToContext context +) { + exists(ObjectInternal obj, string name | receiver(instantiation, context, obj, name) | exists(ObjectInternal cls | cls = obj.getClass() and cls != ObjectInternal::superType() and @@ -356,41 +333,45 @@ predicate method_binding(AttrNode instantiation, ObjectInternal self, CallableOb ) } - /** Helper for method_binding */ -pragma [noinline] +pragma[noinline] predicate receiver(AttrNode instantiation, PointsToContext context, ObjectInternal obj, string name) { PointsToInternal::pointsTo(instantiation.getObject(name), context, obj, _) } /** Helper self parameters: `def meth(self, ...): ...`. */ -pragma [noinline] -private predicate self_parameter(ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls) { +pragma[noinline] +private predicate self_parameter( + ParameterDefinition def, PointsToContext context, PythonClassObjectInternal cls +) { def.isSelf() and /* Exclude the special parameter name `.0` which is used for unfolded comprehensions. */ def.getName() != ".0" and exists(Function scope | def.getScope() = scope and - context.isRuntime() and context.appliesToScope(scope) and + context.isRuntime() and + context.appliesToScope(scope) and scope.getScope() = cls.getScope() and concrete_class(cls) and - /* We want to allow decorated functions, otherwise we lose a lot of useful information. + /* + * We want to allow decorated functions, otherwise we lose a lot of useful information. * However, we want to exclude any function whose arguments are permuted by the decorator. * In general we can't do that, but we can special case the most common ones. */ + neither_class_nor_static_method(scope) ) } -private cached predicate concrete_class(PythonClassObjectInternal cls) { +cached +private predicate concrete_class(PythonClassObjectInternal cls) { cls.getClass() != abcMetaClassObject() or exists(Class c | c = cls.getScope() and not exists(c.getMetaClass()) - | - forall(Function f | - f.getScope() = c | + | + forall(Function f | f.getScope() = c | not exists(Raise r, Name ex | r.getScope() = f and (r.getException() = ex or r.getException().(Call).getFunc() = ex) and @@ -402,8 +383,7 @@ private cached predicate concrete_class(PythonClassObjectInternal cls) { private PythonClassObjectInternal abcMetaClassObject() { /* Avoid using points-to and thus negative recursion */ - exists(Class abcmeta | - result.getScope() = abcmeta | + exists(Class abcmeta | result.getScope() = abcmeta | abcmeta.getName() = "ABCMeta" and abcmeta.getScope().getName() = "abc" ) @@ -412,19 +392,19 @@ private PythonClassObjectInternal abcMetaClassObject() { private predicate neither_class_nor_static_method(Function f) { not exists(f.getADecorator()) or - exists(ControlFlowNode deco | - deco = f.getADecorator().getAFlowNode() | - exists(ObjectInternal o | - PointsToInternal::pointsTo(deco, _, o, _) | + exists(ControlFlowNode deco | deco = f.getADecorator().getAFlowNode() | + exists(ObjectInternal o | PointsToInternal::pointsTo(deco, _, o, _) | o != ObjectInternal::staticMethod() and o != ObjectInternal::classMethod() ) - or not deco instanceof NameNode + or + not deco instanceof NameNode ) } predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name) { - ctx.isImport() and imp.(ImportExprNode).getNode().getAnImportedModuleName() = name and + ctx.isImport() and + imp.(ImportExprNode).getNode().getAnImportedModuleName() = name and ( not exists(Module m | m.getName() = name) and not exists(Builtin b | b.isModule() and b.getName() = name) @@ -441,41 +421,41 @@ predicate missing_imported_module(ControlFlowNode imp, Context ctx, string name) ) } -/* Helper for missing modules to determine if name `x.y` is a module `x.y` or +/* + * Helper for missing modules to determine if name `x.y` is a module `x.y` or * an attribute `y` of module `x`. This list should be added to as required. */ + predicate common_module_name(string name) { name = "zope.interface" or name = "six.moves" } -/** A declaration of a class, either a built-in class or a source definition +/** + * A declaration of a class, either a built-in class or a source definition * This acts as a helper for ClassObjectInternal allowing some lookup without * recursion. */ library class ClassDecl extends @py_object { - ClassDecl() { this.(Builtin).isClass() and not this = Builtin::unknownType() or this.(ControlFlowNode).getNode() instanceof ClassExpr } - string toString() { - result = "ClassDecl" - } + string toString() { result = "ClassDecl" } /** Gets the class scope for Python class declarations */ - Class getClass() { - result = this.(ControlFlowNode).getNode().(ClassExpr).getInnerScope() - } + Class getClass() { result = this.(ControlFlowNode).getNode().(ClassExpr).getInnerScope() } /** Holds if this class declares the attribute `name` */ predicate declaresAttribute(string name) { exists(this.(Builtin).getMember(name)) or - exists(SsaVariable var | name = var.getId() and var.getAUse() = this.getClass().getANormalExit()) + exists(SsaVariable var | + name = var.getId() and var.getAUse() = this.getClass().getANormalExit() + ) } /** Gets the name of this class */ @@ -485,11 +465,11 @@ library class ClassDecl extends @py_object { result = this.getClass().getName() } - /** Whether this is a class whose instances must be treated specially, rather than as generic instances. + /** + * Whether this is a class whose instances must be treated specially, rather than as generic instances. */ predicate isSpecial() { - exists(string name | - this = Builtin::special(name) | + exists(string name | this = Builtin::special(name) | name = "type" or name = "super" or name = "bool" or @@ -505,16 +485,15 @@ library class ClassDecl extends @py_object { /** Holds if for class `C`, `C()` returns an instance of `C` */ predicate callReturnsInstance() { - exists(Class pycls | - pycls = this.getClass() | + exists(Class pycls | pycls = this.getClass() | /* Django does this, so we need to account for it */ not exists(Function init, LocalVariable self | /* `self.__class__ = ...` in the `__init__` method */ pycls.getInitMethod() = init and - self.isSelf() and self.getScope() = init and + self.isSelf() and + self.getScope() = init and exists(AttrNode a | a.isStore() and a.getObject("__class__") = self.getAUse()) - ) - and + ) and not exists(Function new | new.getName() = "__new__" and new.getScope() = pycls) ) or @@ -527,11 +506,9 @@ library class ClassDecl extends @py_object { m.getName() = "_abcoll" or m.getName() = "_collections_abc" - | + | this.getClass().getScope() = m and this.getName() = name ) } - } - diff --git a/python/ql/src/semmle/python/pointsto/Base.qll b/python/ql/src/semmle/python/pointsto/Base.qll index 558c60fcc5c..709f1e3d9e3 100644 --- a/python/ql/src/semmle/python/pointsto/Base.qll +++ b/python/ql/src/semmle/python/pointsto/Base.qll @@ -4,22 +4,24 @@ * to the possible objects it points-to the inferred types of those objects and the 'origin' * of those objects. The 'origin' is the point in source code that the object can be traced * back to. - * + * * This file contains non-layered parts of the points-to analysis. */ + import python import semmle.python.essa.SsaDefinitions private import semmle.python.types.Builtins module BasePointsTo { /** INTERNAL -- Use n.refersTo(value, _, origin) instead */ - pragma [noinline] + pragma[noinline] predicate points_to(ControlFlowNode f, Object value, ControlFlowNode origin) { - ( + ( f.isLiteral() and value = f and not f.getNode() instanceof ImmutableLiteral or f.isFunction() and value = f - ) and origin = f + ) and + origin = f } } @@ -35,12 +37,13 @@ predicate varargs_points_to(ControlFlowNode f, ClassObject cls) { cls = theTupleType() } -/** Gets the class of the object for simple cases, namely constants, functions, +/** + * Gets the class of the object for simple cases, namely constants, functions, * comprehensions and built-in objects. * * This exists primarily for internal use. Use getAnInferredType() instead. */ -pragma [noinline] +pragma[noinline] ClassObject simple_types(Object obj) { result = comprehension(obj.getOrigin()) or @@ -79,37 +82,42 @@ private int tuple_index_value(Object t, int i) { result = t.(TupleNode).getElement(i).getNode().(Num).getN().toInt() or exists(Object item | - py_citems(t, i, item) and + py_citems(t, i, item) and result = item.(NumericObject).intValue() ) } -pragma [noinline] +pragma[noinline] int version_tuple_value(Object t) { - not exists(tuple_index_value(t, 1)) and result = tuple_index_value(t, 0)*10 + not exists(tuple_index_value(t, 1)) and result = tuple_index_value(t, 0) * 10 or - not exists(tuple_index_value(t, 2)) and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + not exists(tuple_index_value(t, 2)) and + result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) or - tuple_index_value(t, 2) = 0 and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + tuple_index_value(t, 2) = 0 and result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) or - tuple_index_value(t, 2) > 0 and result = tuple_index_value(t, 0)*10 + tuple_index_value(t, 1) + 1 + tuple_index_value(t, 2) > 0 and + result = tuple_index_value(t, 0) * 10 + tuple_index_value(t, 1) + 1 } /** Choose a version numbers that represent the extreme of supported versions. */ private int major_minor() { - if major_version() = 3 then - (result = 33 or result = 37) // 3.3 to 3.7 - else - (result = 25 or result = 27) // 2.5 to 2.7 + if major_version() = 3 + then ( + result = 33 or result = 37 + ) else ( + // 3.3 to 3.7 + result = 25 or result = 27 + ) // 2.5 to 2.7 } /** Compares the given tuple object to both the maximum and minimum possible sys.version_info values */ int version_tuple_compare(Object t) { - version_tuple_value(t) < major_minor() and result = -1 + version_tuple_value(t) < major_minor() and result = -1 or - version_tuple_value(t) = major_minor() and result = 0 + version_tuple_value(t) = major_minor() and result = 0 or - version_tuple_value(t) > major_minor() and result = 1 + version_tuple_value(t) > major_minor() and result = 1 } /* Holds if `cls` is a new-style class if it were to have no explicit base classes */ @@ -121,14 +129,15 @@ predicate baseless_is_new_style(ClassObject cls) { exists(cls.declaredMetaClass()) } -/* The following predicates exist in order to provide +/* + * The following predicates exist in order to provide * more precise type information than the underlying * database relations. This help to optimise the points-to * analysis. */ /** Holds if this class (not on a super-class) declares name */ -pragma [noinline] +pragma[noinline] predicate class_declares_attribute(ClassObject cls, string name) { exists(Class defn | defn = cls.getPyClass() and @@ -136,7 +145,7 @@ predicate class_declares_attribute(ClassObject cls, string name) { ) or exists(Builtin o | - o = cls.asBuiltin().getMember(name) and + o = cls.asBuiltin().getMember(name) and not exists(Builtin sup | sup = cls.asBuiltin().getBaseClass() and o = sup.getMember(name) @@ -151,9 +160,9 @@ private predicate class_defines_name(Class cls, string name) { /** Gets a return value CFG node, provided that is safe to track across returns */ ControlFlowNode safe_return_node(PyFunctionObject func) { - result = func.getAReturnedNode() + result = func.getAReturnedNode() and // Not a parameter - and not exists(Parameter p, SsaVariable pvar | + not exists(Parameter p, SsaVariable pvar | p.asName().getAFlowNode() = pvar.getDefinition() and result = pvar.getAUse() ) and @@ -163,9 +172,11 @@ ControlFlowNode safe_return_node(PyFunctionObject func) { /** Holds if it can be determined from the control flow graph alone that this function can never return */ predicate function_can_never_return(FunctionObject func) { - /* A Python function never returns if it has no normal exits that are not dominated by a + /* + * A Python function never returns if it has no normal exits that are not dominated by a * call to a function which itself never returns. */ + exists(Function f | f = func.getFunction() and not exists(f.getAnExitNode()) @@ -174,27 +185,21 @@ predicate function_can_never_return(FunctionObject func) { func = ModuleObject::named("sys").attr("exit") } - -private newtype TIterationDefinition = +private newtype TIterationDefinition = TIterationDefinition_(SsaSourceVariable var, ControlFlowNode def, ControlFlowNode sequence) { SsaSource::iteration_defined_variable(var, def, sequence) } -/** DEPRECATED. For backwards compatibility only. - * A definition of a variable in a for loop `for v in ...:` */ +/** + * DEPRECATED. For backwards compatibility only. + * A definition of a variable in a for loop `for v in ...:` + */ deprecated class IterationDefinition extends TIterationDefinition { + string toString() { result = "IterationDefinition" } - string toString() { - result = "IterationDefinition" - } - - ControlFlowNode getSequence() { - this = TIterationDefinition_(_, _, result) - } - + ControlFlowNode getSequence() { this = TIterationDefinition_(_, _, result) } } - /** Hold if outer contains inner, both are contained within a test and inner is a use is a plain use or an attribute lookup */ pragma[noinline] predicate contains_interesting_expression_within_test(ControlFlowNode outer, ControlFlowNode inner) { @@ -202,7 +207,8 @@ predicate contains_interesting_expression_within_test(ControlFlowNode outer, Con exists(ControlFlowNode test | outer.getAChild*() = inner and test_contains(test, outer) and - test_contains(test, inner) | + test_contains(test, inner) + | inner instanceof NameNode or inner instanceof AttrNode ) @@ -216,10 +222,14 @@ predicate test_contains(ControlFlowNode expr, ControlFlowNode use) { } /** Holds if `test` is a test (a branch), `use` is within that test and `def` is an edge from that test with `sense` */ -predicate refinement_test(ControlFlowNode test, ControlFlowNode use, boolean sense, PyEdgeRefinement def) { - /* Because calls such as `len` may create a new variable, we need to go via the source variable +predicate refinement_test( + ControlFlowNode test, ControlFlowNode use, boolean sense, PyEdgeRefinement def +) { + /* + * Because calls such as `len` may create a new variable, we need to go via the source variable * That is perfectly safe as we are only dealing with calls that do not mutate their arguments. */ + use = def.getInput().getSourceVariable().(Variable).getAUse() and test = def.getPredecessor().getLastNode() and test_contains(test, use) and @@ -227,11 +237,12 @@ predicate refinement_test(ControlFlowNode test, ControlFlowNode use, boolean sen } /** Holds if `f` is an import of the form `from .[...] import name` and the enclosing scope is an __init__ module */ -pragma [noinline] +pragma[noinline] predicate live_import_from_dot_in_init(ImportMemberNode f, EssaVariable var) { exists(string name | import_from_dot_in_init(f.getModule(name)) and - var.getSourceVariable().getName() = name and var.getAUse() = f + var.getSourceVariable().getName() = name and + var.getAUse() = f ) } @@ -247,23 +258,23 @@ predicate import_from_dot_in_init(ImportExprNode f) { } /** Gets the pseudo-object representing the value referred to by an undefined variable */ -Object undefinedVariable() { - py_special_objects(result, "_semmle_undefined_value") -} +Object undefinedVariable() { py_special_objects(result, "_semmle_undefined_value") } /** Gets the pseudo-object representing an unknown value */ -Object unknownValue() { - result.asBuiltin() = Builtin::unknown() -} +Object unknownValue() { result.asBuiltin() = Builtin::unknown() } BuiltinCallable theTypeNewMethod() { result.asBuiltin() = theTypeType().asBuiltin().getMember("__new__") } /** Gets the `value, cls, origin` that `f` would refer to if it has not been assigned some other value */ -pragma [noinline] -predicate potential_builtin_points_to(NameNode f, Object value, ClassObject cls, ControlFlowNode origin) { - f.isGlobal() and f.isLoad() and origin = f and +pragma[noinline] +predicate potential_builtin_points_to( + NameNode f, Object value, ClassObject cls, ControlFlowNode origin +) { + f.isGlobal() and + f.isLoad() and + origin = f and ( builtin_name_points_to(f.getId(), value, cls) or @@ -271,36 +282,41 @@ predicate potential_builtin_points_to(NameNode f, Object value, ClassObject cls, ) } -pragma [noinline] +pragma[noinline] predicate builtin_name_points_to(string name, Object value, ClassObject cls) { value = Object::builtin(name) and cls.asBuiltin() = value.asBuiltin().getClass() } module BaseFlow { - - predicate reaches_exit(EssaVariable var) { - var.getAUse() = var.getScope().getANormalExit() - } + predicate reaches_exit(EssaVariable var) { var.getAUse() = var.getScope().getANormalExit() } /* Helper for this_scope_entry_value_transfer(...). Transfer of values from earlier scope to later on */ - cached predicate scope_entry_value_transfer_from_earlier(EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope) { + cached + predicate scope_entry_value_transfer_from_earlier( + EssaVariable pred_var, Scope pred_scope, ScopeEntryDefinition succ_def, Scope succ_scope + ) { exists(SsaSourceVariable var | reaches_exit(pred_var) and pred_var.getScope() = pred_scope and var = pred_var.getSourceVariable() and var = succ_def.getSourceVariable() and succ_def.getScope() = succ_scope - | + | pred_scope.precedes(succ_scope) or - /* If an `__init__` method does not modify the global variable, then + /* + * If an `__init__` method does not modify the global variable, then * we can skip it and take the value directly from the module. */ + exists(Scope init | - init.getName() = "__init__" and init.precedes(succ_scope) and pred_scope.precedes(init) and - not var.(Variable).getAStore().getScope() = init and var instanceof GlobalVariable + init.getName() = "__init__" and + init.precedes(succ_scope) and + pred_scope.precedes(init) and + not var.(Variable).getAStore().getScope() = init and + var instanceof GlobalVariable ) - ) + ) } } @@ -312,15 +328,17 @@ predicate simple_points_to(ControlFlowNode f, Object value, ClassObject cls, Con or BasePointsTo::points_to(f, value, origin) and cls = simple_types(value) or - value = f.getNode().(ImmutableLiteral).getLiteralObject() and cls = simple_types(value) and origin = f + value = f.getNode().(ImmutableLiteral).getLiteralObject() and + cls = simple_types(value) and + origin = f } -/** Holds if `bit` is a binary expression node with a bitwise operator. +/** + * Holds if `bit` is a binary expression node with a bitwise operator. * Helper for `this_binary_expr_points_to`. */ predicate bitwise_expression_node(BinaryExprNode bit, ControlFlowNode left, ControlFlowNode right) { - exists(Operator op | - op = bit.getNode().getOp() | + exists(Operator op | op = bit.getNode().getOp() | op instanceof BitAnd or op instanceof BitOr or op instanceof BitXor @@ -329,16 +347,14 @@ predicate bitwise_expression_node(BinaryExprNode bit, ControlFlowNode left, Cont right = bit.getRight() } - -private -Module theCollectionsAbcModule() { +private Module theCollectionsAbcModule() { result.getName() = "_abcoll" or result.getName() = "_collections_abc" } ClassObject collectionsAbcClass(string name) { - exists(Class cls | + exists(Class cls | result.getPyClass() = cls and cls.getName() = name and cls.getScope() = theCollectionsAbcModule() diff --git a/python/ql/src/semmle/python/pointsto/CallGraph.qll b/python/ql/src/semmle/python/pointsto/CallGraph.qll index cc618690c32..46471238ec2 100644 --- a/python/ql/src/semmle/python/pointsto/CallGraph.qll +++ b/python/ql/src/semmle/python/pointsto/CallGraph.qll @@ -1,42 +1,47 @@ /** * Context-sensitive call-graph. - * + * * NOTE: Since an "invocation" contains callsite information * and a path back to its ancestor calls, the "invocation" call-graph must be a tree. * This has two important consequences: * 1. The graph is incomplete; it has quite limited depth in order to keep the graph to a sensible size. - * 2. The graph is precise. Since different invocations are distinct, there can be no "cross-talk" between + * 2. The graph is precise. Since different invocations are distinct, there can be no "cross-talk" between * different calls to the same function. */ + import python private import semmle.python.pointsto.PointsToContext -private newtype TTInvocation = TInvocation(FunctionObject f, Context c) { - exists(Context outer, CallNode call | - call = f.getACall(outer) and - c.fromCall(call, outer) - ) - or - c.appliesToScope(f.getFunction()) -} +private newtype TTInvocation = + TInvocation(FunctionObject f, Context c) { + exists(Context outer, CallNode call | + call = f.getACall(outer) and + c.fromCall(call, outer) + ) + or + c.appliesToScope(f.getFunction()) + } -/** This class represents a static approximation to the - * dynamic call-graph. A `FunctionInvocation` represents +/** + * This class represents a static approximation to the + * dynamic call-graph. A `FunctionInvocation` represents * all calls made to a function for a given context. */ class FunctionInvocation extends TTInvocation { - string toString() { result = "Invocation" } FunctionObject getFunction() { this = TInvocation(result, _) } Context getContext() { this = TInvocation(_, result) } - /** Gets the callee invocation for the given callsite. + /** + * Gets the callee invocation for the given callsite. * The callsite must be within the function of this invocation. */ FunctionInvocation getCallee(CallNode call) { - exists(FunctionObject callee, Context callee_context, FunctionObject caller, Context caller_context | + exists( + FunctionObject callee, Context callee_context, FunctionObject caller, Context caller_context + | this = TInvocation(caller, caller_context) and result = TInvocation(callee, callee_context) and call = callee.getACall(caller_context) and @@ -45,12 +50,11 @@ class FunctionInvocation extends TTInvocation { ) } - /** Gets a callee invocation. + /** + * Gets a callee invocation. * That is any invocation made from within this invocation. */ - FunctionInvocation getACallee() { - result = this.getCallee(_) - } + FunctionInvocation getACallee() { result = this.getCallee(_) } /** Holds if this is an invocation `f` in the "runtime" context. */ predicate runtime(FunctionObject f) { @@ -61,13 +65,8 @@ class FunctionInvocation extends TTInvocation { } /** Gets the call from which this invocation was made. */ - CallNode getCall() { - this.getContext().fromCall(result, _) - } + CallNode getCall() { this.getContext().fromCall(result, _) } /** Gets the caller invocation of this invocation, if any. */ - FunctionInvocation getCaller() { - this = result.getCallee(_) - } - + FunctionInvocation getCaller() { this = result.getCallee(_) } } diff --git a/python/ql/src/semmle/python/pointsto/Filters.qll b/python/ql/src/semmle/python/pointsto/Filters.qll index 927e6a429de..114711b217c 100644 --- a/python/ql/src/semmle/python/pointsto/Filters.qll +++ b/python/ql/src/semmle/python/pointsto/Filters.qll @@ -1,8 +1,8 @@ -/** Helper predicates for standard tests in Python commonly +/** + * Helper predicates for standard tests in Python commonly * used to filter objects by value or by type. */ - import python /** Holds if `c` is a call to `hasattr(obj, attr)`. */ @@ -21,13 +21,15 @@ predicate is_callable(CallNode c, ControlFlowNode obj) { /** Holds if `c` is a call to `isinstance(use, cls)`. */ predicate isinstance(CallNode fc, ControlFlowNode cls, ControlFlowNode use) { fc.getFunction().(NameNode).getId() = "isinstance" and - cls = fc.getArg(1) and fc.getArg(0) = use + cls = fc.getArg(1) and + fc.getArg(0) = use } /** Holds if `c` is a call to `issubclass(use, cls)`. */ predicate issubclass(CallNode fc, ControlFlowNode cls, ControlFlowNode use) { fc.getFunction().(NameNode).getId() = "issubclass" and - fc.getArg(0) = use and cls = fc.getArg(1) + fc.getArg(0) = use and + cls = fc.getArg(1) } /** Holds if `c` is a test comparing `x` and `y`. `is` is true if the operator is `is` or `==`, it is false if the operator is `is not` or `!=`. */ @@ -35,11 +37,15 @@ predicate equality_test(CompareNode c, ControlFlowNode x, boolean is, ControlFlo exists(Cmpop op | c.operands(x, op, y) or c.operands(y, op, x) - | - (is = true and op instanceof Is or - is = false and op instanceof IsNot or - is = true and op instanceof Eq or - is = false and op instanceof NotEq + | + ( + is = true and op instanceof Is + or + is = false and op instanceof IsNot + or + is = true and op instanceof Eq + or + is = false and op instanceof NotEq ) ) } diff --git a/python/ql/src/semmle/python/pointsto/Final.qll b/python/ql/src/semmle/python/pointsto/Final.qll index a1f14b0f87c..b02c42852a1 100644 --- a/python/ql/src/semmle/python/pointsto/Final.qll +++ b/python/ql/src/semmle/python/pointsto/Final.qll @@ -1,6 +1,5 @@ /* For backwards compatibility */ - import PointsTo::PointsTo as P /** DEPRECATED: Use `PointsTo` instead */ -deprecated module FinalPointsTo = P; \ No newline at end of file +deprecated module FinalPointsTo = P; diff --git a/python/ql/src/semmle/python/pointsto/MRO.qll b/python/ql/src/semmle/python/pointsto/MRO.qll index 98e8eea9bbd..cc159ecbb0f 100644 --- a/python/ql/src/semmle/python/pointsto/MRO.qll +++ b/python/ql/src/semmle/python/pointsto/MRO.qll @@ -1,4 +1,5 @@ -/** Classes and predicates for computing the Method Resolution Order (MRO) of classes. +/** + * Classes and predicates for computing the Method Resolution Order (MRO) of classes. * Supports both old-style (diamond) inheritance and new-style (C3 linearization) inheritance. */ @@ -17,19 +18,16 @@ */ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.types.Builtins - -cached newtype TClassList = Empty() - or - Cons(ClassObjectInternal head, TClassList tail) { - required_cons(head, tail) - } +cached +newtype TClassList = + Empty() or + Cons(ClassObjectInternal head, TClassList tail) { required_cons(head, tail) } /* Keep ClassList finite and as small as possible */ private predicate required_cons(ClassObjectInternal head, ClassList tail) { @@ -38,7 +36,7 @@ private predicate required_cons(ClassObjectInternal head, ClassList tail) { tail = merge_of_linearization_of_bases(head) or exists(ClassObjectInternal cls, int n | - head = Types::getBase(cls, n) and tail = bases(cls, n+1) + head = Types::getBase(cls, n) and tail = bases(cls, n + 1) ) or head = ObjectInternal::builtin("object") and tail = Empty() @@ -52,12 +50,12 @@ private predicate required_cons(ClassObjectInternal head, ClassList tail) { or exists(ClassList list, int n | n = list.firstIndex(head) and - tail = list.deduplicate(n+1) + tail = list.deduplicate(n + 1) ) or exists(ClassListList list, int n | head = list.getHead().getItem(n) and - tail = flatten_list(list, n+1) + tail = flatten_list(list, n + 1) ) or tail = list_old_style_base_mros(head).flatten() @@ -70,16 +68,12 @@ private ClassObjectInternal sole_base(ClassObjectInternal cls) { /** A list of classes, used to represent the MRO of a class */ class ClassList extends TClassList { - - string toString() { - result = "[" + this.contents() + "]" - } + string toString() { result = "[" + this.contents() + "]" } string contents() { this = Empty() and result = "" or - exists(ClassObjectInternal head | - head = this.getHead() | + exists(ClassObjectInternal head | head = this.getHead() | this.getTail() = Empty() and result = className(head) or this.getTail() != Empty() and result = className(head) + ", " + this.getTail().contents() @@ -98,25 +92,19 @@ class ClassList extends TClassList { result = this.getTail().length() + 1 } - ClassObjectInternal getHead() { - this = Cons(result, _) - } + ClassObjectInternal getHead() { this = Cons(result, _) } - ClassList getTail() { - this = Cons(_, result) - } + ClassList getTail() { this = Cons(_, result) } ClassObjectInternal getItem(int n) { - n = 0 and result = this.getHead() + n = 0 and result = this.getHead() or - result = this.getTail().getItem(n-1) + result = this.getTail().getItem(n - 1) } - ClassObjectInternal getAnItem() { - result = this.getItem(_) - } + ClassObjectInternal getAnItem() { result = this.getItem(_) } - pragma [inline] + pragma[inline] ClassList removeHead(ClassObjectInternal cls) { this.getHead() = cls and result = this.getTail() or @@ -159,18 +147,15 @@ class ClassList extends TClassList { } ClassObjectInternal findDeclaringClass(string name) { - exists(ClassDecl head | - head = this.getHead().getClassDeclaration() | - if head.declaresAttribute(name) then - result = this.getHead() - else - result = this.getTail().findDeclaringClass(name) + exists(ClassDecl head | head = this.getHead().getClassDeclaration() | + if head.declaresAttribute(name) + then result = this.getHead() + else result = this.getTail().findDeclaringClass(name) ) } predicate lookup(string name, ObjectInternal value, CfgOrigin origin) { - exists(ClassObjectInternal decl | - decl = this.findDeclaringClass(name) | + exists(ClassObjectInternal decl | decl = this.findDeclaringClass(name) | Types::declaredAttribute(decl, name, value, origin) ) } @@ -182,83 +167,63 @@ class ClassList extends TClassList { } ClassList startingAt(ClassObjectInternal cls) { - exists(ClassObjectInternal head | - head = this.getHead() | - if head = cls then - result = this - else - result = this.getTail().startingAt(cls) + exists(ClassObjectInternal head | head = this.getHead() | + if head = cls then result = this else result = this.getTail().startingAt(cls) ) } - ClassList deduplicate() { - result = this.deduplicate(0) - } + ClassList deduplicate() { result = this.deduplicate(0) } /* Helpers for `deduplicate()` */ - - int firstIndex(ClassObjectInternal cls) { - result = this.firstIndex(cls, 0) - } + int firstIndex(ClassObjectInternal cls) { result = this.firstIndex(cls, 0) } /* Helper for firstIndex(cls), getting the first index of `cls` where result >= n */ private int firstIndex(ClassObjectInternal cls, int n) { this.getItem(n) = cls and result = n or - this.getItem(n) != cls and result = this.firstIndex(cls, n+1) + this.getItem(n) != cls and result = this.firstIndex(cls, n + 1) } /** Holds if the class at `n` is a duplicate of an earlier position. */ private predicate duplicate(int n) { - exists(ClassObjectInternal cls | - cls = this.getItem(n) and this.firstIndex(cls) < n - ) + exists(ClassObjectInternal cls | cls = this.getItem(n) and this.firstIndex(cls) < n) } - /** Gets a class list which is the de-duplicated form of the list containing elements of + /** + * Gets a class list which is the de-duplicated form of the list containing elements of * this list from `n` onwards. */ ClassList deduplicate(int n) { n = this.length() and result = Empty() or - this.duplicate(n) and result = this.deduplicate(n+1) + this.duplicate(n) and result = this.deduplicate(n + 1) or exists(ClassObjectInternal cls | n = this.firstIndex(cls) and - result = Cons(cls, this.deduplicate(n+1)) + result = Cons(cls, this.deduplicate(n + 1)) ) } - predicate isEmpty() { - this = Empty() - } + predicate isEmpty() { this = Empty() } - ClassList reverse() { - reverse_step(this, Empty(), result) - } + ClassList reverse() { reverse_step(this, Empty(), result) } - /** Holds if this MRO contains a class whose instances we treat specially, rather than as a generic instance. + /** + * Holds if this MRO contains a class whose instances we treat specially, rather than as a generic instance. * For example, `type` or `int`. */ boolean containsSpecial() { this = Empty() and result = false or - exists(ClassDecl decl | - decl = this.getHead().getClassDeclaration() | - if decl.isSpecial() then - result = true - else - result = this.getTail().containsSpecial() + exists(ClassDecl decl | decl = this.getHead().getClassDeclaration() | + if decl.isSpecial() then result = true else result = this.getTail().containsSpecial() ) } - } private newtype TClassListList = EmptyList() or - ConsList(TClassList head, TClassListList tail) { - required_list(head, tail) - } + ConsList(TClassList head, TClassListList tail) { required_list(head, tail) } /* Keep ClassListList finite and as small as possible */ private predicate required_list(ClassList head, ClassListList tail) { @@ -268,26 +233,22 @@ private predicate required_list(ClassList head, ClassListList tail) { or exists(ClassObjectInternal cls, int n | head = Mro::newStyleMro(Types::getBase(cls, n)) and - tail = list_of_linearization_of_bases_plus_bases(cls, n+1) + tail = list_of_linearization_of_bases_plus_bases(cls, n + 1) ) or exists(ClassObjectInternal cls, int n | head = Mro::oldStyleMro(Types::getBase(cls, n)) and - tail = list_old_style_base_mros(cls, n+1) + tail = list_old_style_base_mros(cls, n + 1) ) } private class ClassListList extends TClassListList { - - string toString() { - result = "[" + this.contents() + "]" - } + string toString() { result = "[" + this.contents() + "]" } string contents() { this = EmptyList() and result = "" or - exists(ClassList head | - head = this.getHead() | + exists(ClassList head | head = this.getHead() | this.getTail() = EmptyList() and result = head.toString() or this.getTail() != EmptyList() and result = head.toString() + ", " + this.getTail().contents() @@ -300,18 +261,14 @@ private class ClassListList extends TClassListList { result = this.getTail().length() + 1 } - ClassList getHead() { - this = ConsList(result, _) - } + ClassList getHead() { this = ConsList(result, _) } - ClassListList getTail() { - this = ConsList(_, result) - } + ClassListList getTail() { this = ConsList(_, result) } ClassList getItem(int n) { n = 0 and result = this.getHead() or - result = this.getTail().getItem(n-1) + result = this.getTail().getItem(n - 1) } private ClassObjectInternal getAHead() { @@ -320,7 +277,7 @@ private class ClassListList extends TClassListList { result = this.getTail().getAHead() } - pragma [nomagic] + pragma[nomagic] ClassList merge() { exists(ClassList reversed | merge_step(reversed, EmptyList(), this) and @@ -331,13 +288,17 @@ private class ClassListList extends TClassListList { } /* Join ordering helper */ - pragma [noinline] - predicate removedClassParts(ClassObjectInternal cls, ClassList removed_head, ClassListList removed_tail, int n) { - cls = this.bestMergeCandidate() and n = this.length()-1 and - removed_head = this.getItem(n).removeHead(cls) and removed_tail = EmptyList() + pragma[noinline] + predicate removedClassParts( + ClassObjectInternal cls, ClassList removed_head, ClassListList removed_tail, int n + ) { + cls = this.bestMergeCandidate() and + n = this.length() - 1 and + removed_head = this.getItem(n).removeHead(cls) and + removed_tail = EmptyList() or exists(ClassList prev_head, ClassListList prev_tail | - this.removedClassParts(cls, prev_head, prev_tail, n+1) and + this.removedClassParts(cls, prev_head, prev_tail, n + 1) and removed_head = this.getItem(n).removeHead(cls) and removed_tail = ConsList(prev_head, prev_tail) ) @@ -356,12 +317,10 @@ private class ClassListList extends TClassListList { cls = this.getAHead() and n = this.length() or this.getItem(n).legalMergeHead(cls) and - this.legalMergeCandidate(cls, n+1) + this.legalMergeCandidate(cls, n + 1) } - predicate legalMergeCandidate(ClassObjectInternal cls) { - this.legalMergeCandidate(cls, 0) - } + predicate legalMergeCandidate(ClassObjectInternal cls) { this.legalMergeCandidate(cls, 0) } predicate illegalMergeCandidate(ClassObjectInternal cls) { cls = this.getAHead() and @@ -369,20 +328,17 @@ private class ClassListList extends TClassListList { } ClassObjectInternal bestMergeCandidate(int n) { - exists(ClassObjectInternal head | - head = this.getItem(n).getHead() - | + exists(ClassObjectInternal head | head = this.getItem(n).getHead() | legalMergeCandidate(head) and result = head or - illegalMergeCandidate(head) and result = this.bestMergeCandidate(n+1) + illegalMergeCandidate(head) and result = this.bestMergeCandidate(n + 1) ) } - ClassObjectInternal bestMergeCandidate() { - result = this.bestMergeCandidate(0) - } + ClassObjectInternal bestMergeCandidate() { result = this.bestMergeCandidate(0) } - /** Gets a ClassList representing the this list of list flattened into a single list. + /** + * Gets a ClassList representing the this list of list flattened into a single list. * Used for old-style MRO computation. */ ClassList flatten() { @@ -390,17 +346,14 @@ private class ClassListList extends TClassListList { or result = flatten_list(this, 0) } - } private ClassList flatten_list(ClassListList list, int n) { need_flattening(list) and - exists(ClassList head, ClassListList tail | - list = ConsList(head, tail) - | + exists(ClassList head, ClassListList tail | list = ConsList(head, tail) | n = head.length() and result = tail.flatten() or - result = Cons(head.getItem(n), flatten_list(list, n+1)) + result = Cons(head.getItem(n), flatten_list(list, n + 1)) ) } @@ -414,12 +367,10 @@ private predicate need_flattening(ClassListList list) { ) } -private ClassList bases(ClassObjectInternal cls) { - result = bases(cls, 0) -} +private ClassList bases(ClassObjectInternal cls) { result = bases(cls, 0) } private ClassList bases(ClassObjectInternal cls, int n) { - result = Cons(Types::getBase(cls, n), bases(cls, n+1)) + result = Cons(Types::getBase(cls, n), bases(cls, n + 1)) or result = Empty() and n = Types::base_count(cls) } @@ -432,7 +383,7 @@ private ClassListList list_of_linearization_of_bases_plus_bases(ClassObjectInter result = ConsList(bases(cls), EmptyList()) and n = Types::base_count(cls) and n > 1 or exists(ClassListList partial | - partial = list_of_linearization_of_bases_plus_bases(cls, n+1) and + partial = list_of_linearization_of_bases_plus_bases(cls, n + 1) and result = ConsList(Mro::newStyleMro(Types::getBase(cls, n)), partial) ) } @@ -445,18 +396,23 @@ private ClassListList list_old_style_base_mros(ClassObjectInternal cls) { result = list_old_style_base_mros(cls, 0) } -pragma [nomagic] +pragma[nomagic] private ClassListList list_old_style_base_mros(ClassObjectInternal cls, int n) { n = Types::base_count(cls) and result = EmptyList() or - result = ConsList(Mro::oldStyleMro(Types::getBase(cls, n)), list_old_style_base_mros(cls, n+1)) + result = ConsList(Mro::oldStyleMro(Types::getBase(cls, n)), list_old_style_base_mros(cls, n + 1)) } -/** Holds if the pair `reversed_mro`, `remaining_list` represents a step in the C3 merge operation +/** + * Holds if the pair `reversed_mro`, `remaining_list` represents a step in the C3 merge operation * of computing the C3 linearization of `original`. */ -private predicate merge_step(ClassList reversed_mro, ClassListList remaining_list, ClassListList original) { - remaining_list = list_of_linearization_of_bases_plus_bases(_) and reversed_mro = Empty() and remaining_list = original +private predicate merge_step( + ClassList reversed_mro, ClassListList remaining_list, ClassListList original +) { + remaining_list = list_of_linearization_of_bases_plus_bases(_) and + reversed_mro = Empty() and + remaining_list = original or /* Removes the best merge candidate from `remaining_list` and prepends it to `reversed_mro` */ exists(ClassObjectInternal head, ClassList prev_reverse_mro, ClassListList prev_list | @@ -470,7 +426,6 @@ private predicate merge_step(ClassList reversed_mro, ClassListList remaining_lis } /* Helpers for `ClassList.reverse()` */ - private predicate needs_reversing(ClassList lst) { merge_step(lst, EmptyList(), _) or @@ -487,8 +442,8 @@ private predicate reverse_step(ClassList lst, ClassList remainder, ClassList rev } module Mro { - - cached ClassList newStyleMro(ClassObjectInternal cls) { + cached + ClassList newStyleMro(ClassObjectInternal cls) { cls = ObjectInternal::builtin("object") and result = Cons(cls, Empty()) or result = Cons(cls, merge_of_linearization_of_bases(cls)) @@ -496,9 +451,9 @@ module Mro { result = Cons(cls, newStyleMro(sole_base(cls))) } - cached ClassList oldStyleMro(ClassObjectInternal cls) { + cached + ClassList oldStyleMro(ClassObjectInternal cls) { Types::isOldStyle(cls) and result = Cons(cls, list_old_style_base_mros(cls).flatten()).(ClassList).deduplicate() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/pointsto/Overview.qll b/python/ql/src/semmle/python/pointsto/Overview.qll index aae2e04f018..7e343f8934a 100644 --- a/python/ql/src/semmle/python/pointsto/Overview.qll +++ b/python/ql/src/semmle/python/pointsto/Overview.qll @@ -1,45 +1,45 @@ + /* - * * ## Points-to analysis for Python - * - * + * + * * The purpose of points-to analysis is to determine what values a variable might hold at runtime. * This allows us to write useful queries to check for the misuse of those values. * In the academic and technical literature, points-to analysis (AKA pointer analysis) attempts to determine which variables can refer to which heap allocated objects. * From the point of view of Python we can treat all Python objects as "heap allocated objects". - * - * + * + * * The output of the points-to analysis consists of a large set of relations which provide not only points-to information, but call-graph, pruned flow-graph and exception-raising information. - * - * These relations are computed by a large set of mutually recursive predicates which infer the flow of values through the program. + * + * These relations are computed by a large set of mutually recursive predicates which infer the flow of values through the program. * Our analysis is inter-procedural use contexts to maintain the precision of an intra-procedural analysis. - * + * * ### Precision - * + * * In conventional points-to, the computed points-to set should be a super-set of the real points-to set (were it possible to determine such a thing). - * However for our purposes we want the points-to set to be a sub-set of the real points-to set. - * This is simply because conventional points-to is used to determine compiler optimisations, so the points-to set needs to be a conservative over-estimate of what is possible. + * However for our purposes we want the points-to set to be a sub-set of the real points-to set. + * This is simply because conventional points-to is used to determine compiler optimisations, so the points-to set needs to be a conservative over-estimate of what is possible. * We have the opposite concern; we want to eliminate false positives where possible. - * - * This should be born in mind when reading the literature about points-to analysis. In conventional points-to, a precise analysis produces as small a points-to set as possible. + * + * This should be born in mind when reading the literature about points-to analysis. In conventional points-to, a precise analysis produces as small a points-to set as possible. * Our analysis is precise (or very close to it). Instead of seeking to maximise precision, we seek to maximise *recall* and produce as large a points-to set as possible (whilst remaining precise). - * + * * When it comes to designing the inference, we always choose precision over recall. * We want to minimise false positives so it is important to avoid making incorrect inferences, even if it means losing a lot of potential information. * If a potential new points-to fact would increase the number of values we are able to infer, but decrease precision, then we omit it. - * + * * ###Objects - * - * In convention points-to an 'object' is generally considered to be any static instantiation. E.g. in Java this is simply anything looking like `new X(..)`. - * However, in Python as there is no `new` expression we cannot known what is a class merely from the syntax. + * + * In convention points-to an 'object' is generally considered to be any static instantiation. E.g. in Java this is simply anything looking like `new X(..)`. + * However, in Python as there is no `new` expression we cannot known what is a class merely from the syntax. * Consequently, we must start with only with the simplest objects and extend to instance creation as we can infer classes. - * + * * To perform points-to analysis we start with the set of built-in objects, all literal constants, and class and function definitions. * From there we can propagate those values. Whenever we see a call `x()` we add a new object if `x` refers to some class. - * + * * In the `PointsTo::points_to` relation, the second argument, `Object value` is the "value" referred to by the ControlFlowNode (which will correspond to an rvalue in the source code). * The set of "values" used will change as the library continues to improve, but currently include the following: - * + * * * Classes (both in the source and builtin) * * Functions (both in the source and builtin) * * Literal constants defined in the source (string and numbers) @@ -49,56 +49,56 @@ * * Bound methods, static- and class-methods, and properties. * * Instances of `super`. * * Missing modules, where no concrete module is found for an import. - * + * * A number of constructs that might create a new object, such as binary operations, are omitted if there is no useful information to can be attached to them and they would just increase the size of the database. - * + * * ###Contexts - * - * In order to better handle value tracking in functions, we introduce context to the points-to relation. + * + * In order to better handle value tracking in functions, we introduce context to the points-to relation. * There is one `default` context, equivalent to having no context, a `main` context for scripts and any number of call-site contexts. - * - * Adding context to a conventional points-to analysis can significantly improve its precision. Whereas, for our points-to analysis adding context significantly improves the recall of our analysis. - * The consensus in the academic literature is that "object sensitivity" is superior to "call-site sensitivity". + * + * Adding context to a conventional points-to analysis can significantly improve its precision. Whereas, for our points-to analysis adding context significantly improves the recall of our analysis. + * The consensus in the academic literature is that "object sensitivity" is superior to "call-site sensitivity". * However, since we are seeking to maximise not minimise our points-to set, it is entirely possible that the reverse is true for us. * We use "call-site sensitivity" at the moment, although the exact set of contexts used will change. - * + * * ### Points-to analysis over the ESSA dataflow graph - * + * * In order to perform points-to analysis on the dataflow graph, we * need to understand the many implicit "definitions" that occur within Python code. - * + * * These are: - * + * * 1. Implicit definition as "undefined" for any local or global variable at the start of its scope. * Many of these will be dead and will be eliminated during construction of the dataflow graph. * 2. Implicit definition of `__name__`, `__package__` and `__module__` at the start of the relevant scopes. * 3. Implicit definition of all submodules as global variables at the start of an `__init__` module - * + * * In addition, there are the "artificial", data-flow definitions: - * + * * 1. Phi functions * 2. Pi (guard, or filter) functions. * 3. "Refinements" of a variable. These are not definitions of the variable, but may modify the object referred to by the variable, * possibly changing some inferred facts about the object. * 4. Definition of any variable that escapes the scope, at entry, exit and at all call-sites. - * + * * As an example, consider: * ```python * if a: * float = "global" * #float can now be either the class 'float' or the string "global" - * + * * class C2: * if b: * float = "local" * float - * + * * float #Cannot be "local" * ``` - * + * * Ignoring `__name__` and `__package__`, the data-flow graph looks something like this, noting that there are two variables named "float" * in the scope `C2`, the local and the global. - * + * * ``` * a_0 = undefined * b_0 = undefined @@ -112,14 +112,14 @@ * float_6 = phi(float_4, float_5) | * float_7 = float_3 (transfer values in global 'float', but not local, back to module scope). * ``` - * + * * ### Implementation - * + * * This section is for information purposes only. Any or all details may change without notice. - * + * * QL, being based on Datalog, has fixed-point semantics which makes it impossible to make negative statements that are recursive. * To work around this we need to define many predicates over boolean variables. Suppose we have a predicate with determines whether a test can be true or false at runtime. * We might naively implement this as `predicate test_is_true(ControlFlowNode test, Context ctx)` but this would lead to negative recursion if we want to know when the test can be false. * Instead we implement it as `boolean test_result(ControlFlowNode test, Context ctx)` where the absence of a value indicates merely that we do (yet) know what value the test may have. - * */ + diff --git a/python/ql/src/semmle/python/pointsto/PointsTo.qll b/python/ql/src/semmle/python/pointsto/PointsTo.qll index cdfcceb2c8b..9bcead16c13 100644 --- a/python/ql/src/semmle/python/pointsto/PointsTo.qll +++ b/python/ql/src/semmle/python/pointsto/PointsTo.qll @@ -1,5 +1,4 @@ import python - private import semmle.python.objects.TObject private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.Filters @@ -10,13 +9,13 @@ private import semmle.python.types.Extensions /* Use this version for speed */ library class CfgOrigin extends @py_object { - string toString() { /* Not to be displayed */ result = "CfgOrigin" } - /** Get a `ControlFlowNode` from `this` or `here`. + /** + * Get a `ControlFlowNode` from `this` or `here`. * If `this` is a ControlFlowNode then use that, otherwise fall back on `here` */ pragma[inline] @@ -26,36 +25,24 @@ library class CfgOrigin extends @py_object { not this instanceof ControlFlowNode and result = here } - ControlFlowNode toCfgNode() { - result = this - } + ControlFlowNode toCfgNode() { result = this } pragma[inline] CfgOrigin fix(ControlFlowNode here) { - if this = Builtin::unknown() then - result = here - else - result = this + if this = Builtin::unknown() then result = here else result = this } - } module CfgOrigin { + CfgOrigin fromCfgNode(ControlFlowNode f) { result = f } - CfgOrigin fromCfgNode(ControlFlowNode f) { - result = f - } - - CfgOrigin unknown() { - result = Builtin::unknown() - } + CfgOrigin unknown() { result = Builtin::unknown() } CfgOrigin fromObject(ObjectInternal obj) { obj.isBuiltin() and result = unknown() or result = obj.getOrigin() } - } /* Use this version for stronger type-checking */ @@ -111,88 +98,104 @@ module CfgOrigin { // } // //} - /* The API */ module PointsTo { - - predicate pointsTo(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate pointsTo( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::pointsTo(f, context, value, origin) } - predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + predicate variablePointsTo( + EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { PointsToInternal::variablePointsTo(var, context, value, origin) } /* Backwards compatibility */ - deprecated cached predicate - points_to(ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin) { + cached + deprecated predicate points_to( + ControlFlowNode f, PointsToContext context, Object obj, ClassObject cls, ControlFlowNode origin + ) { exists(ObjectInternal value | PointsToInternal::pointsTo(f, context, value, origin) and - cls = value.getClass().getSource() | - obj = value.getSource() or + cls = value.getClass().getSource() + | + obj = value.getSource() + or value.useOriginAsLegacyObject() and obj = origin ) or /* Backwards compatibility for *args and **kwargs */ - exists(Function func | - obj = f and origin = f and context.isRuntime() | - func.getVararg() = f.getNode() and cls = theTupleType() or + exists(Function func | obj = f and origin = f and context.isRuntime() | + func.getVararg() = f.getNode() and cls = theTupleType() + or func.getKwarg() = f.getNode() and cls = theDictType() ) or not f.isParameter() and exists(ObjectInternal value | PointsToInternal::pointsTo(f.(DefinitionNode).getValue(), context, value, origin) and - cls = value.getClass().getSource() | - obj = value.getSource() or + cls = value.getClass().getSource() + | + obj = value.getSource() + or value.useOriginAsLegacyObject() and obj = origin ) } - deprecated predicate - ssa_variable_points_to(EssaVariable var, PointsToContext context, Object obj, ClassObject cls, CfgOrigin origin) { + deprecated predicate ssa_variable_points_to( + EssaVariable var, PointsToContext context, Object obj, ClassObject cls, CfgOrigin origin + ) { exists(ObjectInternal value | PointsToInternal::variablePointsTo(var, context, value, origin) and - cls = value.getClass().getSource() | + cls = value.getClass().getSource() + | obj = value.getSource() ) } - deprecated - CallNode get_a_call(Object func, PointsToContext context) { + deprecated CallNode get_a_call(Object func, PointsToContext context) { exists(ObjectInternal value | result = value.(Value).getACall(context) and func = value.getSource() ) } - cached predicate moduleExports(ModuleObjectInternal mod, string name) { + cached + predicate moduleExports(ModuleObjectInternal mod, string name) { InterModulePointsTo::moduleExportsBoolean(mod, name) = true } - } -cached module PointsToInternal { - +cached +module PointsToInternal { pragma[noinline] - cached predicate importCtxPointsTo(ControlFlowNode f, ObjectInternal value, ControlFlowNode origin) { - PointsToInternal::pointsTo(f, any(Context ctx | ctx.isImport()), value, origin) + cached + predicate importCtxPointsTo(ControlFlowNode f, ObjectInternal value, ControlFlowNode origin) { + PointsToInternal::pointsTo(f, any(Context ctx | ctx.isImport()), value, origin) } /** INTERNAL -- Use `f.refersTo(value, origin)` instead. */ - cached predicate pointsTo(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + cached + predicate pointsTo( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { points_to_candidate(f, context, value, origin) and reachableBlock(f.getBasicBlock(), context) } - cached predicate pointsToString(ControlFlowNode f, PointsToContext context, string value) { + cached + predicate pointsToString(ControlFlowNode f, PointsToContext context, string value) { exists(ObjectInternal str | PointsToInternal::pointsTo(f, context, str, _) and str.strValue() = value ) } - private predicate points_to_candidate(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate points_to_candidate( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { use_points_to(f, context, value, origin) or attribute_load_points_to(f, context, value, origin) @@ -216,18 +219,21 @@ cached module PointsToInternal { iteration_points_to(f, context, value, origin) } - /** Holds if the attribute `name` is required for `obj` + /** + * Holds if the attribute `name` is required for `obj` * For object `x` and attribute `name` it means that there exists somewhere in the code * `x.name` or `getattr(x, "name")`. */ - cached predicate attributeRequired(ObjectInternal obj, string name) { + cached + predicate attributeRequired(ObjectInternal obj, string name) { pointsTo(any(AttrNode a).getObject(name), _, obj, _) or Expressions::getattr_call(_, _, _, obj, name) } /* Holds if BasicBlock `b` is reachable, given the context `context`. */ - cached predicate reachableBlock(BasicBlock b, PointsToContext context) { + cached + predicate reachableBlock(BasicBlock b, PointsToContext context) { exists(Scope scope | context.appliesToScope(scope) and scope.getEntryNode().getBasicBlock() = b @@ -250,7 +256,7 @@ cached module PointsToInternal { test = pred.getLastNode() and pointsTo(test, context, value, _) and sense = value.booleanValue() - | + | sense = true and succ = pred.getATrueSuccessor() or sense = false and succ = pred.getAFalseSuccessor() @@ -259,28 +265,37 @@ cached module PointsToInternal { } /** Gets an object pointed to by a use (of a variable). */ - pragma [noinline] - private predicate use_points_to(NameNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate use_points_to( + NameNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(CfgOrigin origin_or_obj | value != ObjectInternal::undefined() and - use_points_to_maybe_origin(f, context, value, origin_or_obj) | + use_points_to_maybe_origin(f, context, value, origin_or_obj) + | origin = origin_or_obj.asCfgNodeOrHere(f) ) } - pragma [noinline] - private predicate use_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { - variablePointsTo(fast_local_variable(f), context, value, origin_or_obj) + pragma[noinline] + private predicate use_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { + variablePointsTo(fast_local_variable(f), context, value, origin_or_obj) or name_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) or - not exists(fast_local_variable(f)) and not exists(name_local_variable(f)) and + not exists(fast_local_variable(f)) and + not exists(name_local_variable(f)) and global_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) } /** Holds if `var` refers to `(value, origin)` given the context `context`. */ - pragma [noinline] - cached predicate variablePointsTo(EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + cached + predicate variablePointsTo( + EssaVariable var, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { ssa_definition_points_to(var.getDefinition(), context, value, origin) or exists(EssaVariable prev | @@ -299,16 +314,21 @@ cached module PointsToInternal { end.getDefinition() = def ) or - /* Ignore the effects of calls on their arguments. PointsTo is an approximation, - * but attempting to improve accuracy would be very expensive for very little gain. */ + /* + * Ignore the effects of calls on their arguments. PointsTo is an approximation, + * but attempting to improve accuracy would be very expensive for very little gain. + */ + exists(ArgumentRefinement def | start = def.getInput() and end.getDefinition() = def ) } - pragma [noinline] - private predicate name_lookup_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { + pragma[noinline] + private predicate name_lookup_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { exists(EssaVariable var | var = name_local_variable(f) | variablePointsTo(var, context, value, origin_or_obj) ) @@ -317,22 +337,23 @@ cached module PointsToInternal { global_lookup_points_to_maybe_origin(f, context, value, origin_or_obj) } - pragma [noinline] + pragma[noinline] private predicate local_variable_undefined(NameNode f, PointsToContext context) { variablePointsTo(name_local_variable(f), context, ObjectInternal::undefined(), _) } - pragma [noinline] - private predicate global_lookup_points_to_maybe_origin(NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj) { + pragma[noinline] + private predicate global_lookup_points_to_maybe_origin( + NameNode f, PointsToContext context, ObjectInternal value, CfgOrigin origin_or_obj + ) { variablePointsTo(global_variable(f), context, value, origin_or_obj) or - exists(ControlFlowNode origin | - origin_or_obj = CfgOrigin::fromCfgNode(origin) - | + exists(ControlFlowNode origin | origin_or_obj = CfgOrigin::fromCfgNode(origin) | variablePointsTo(global_variable(f), context, ObjectInternal::undefined(), _) and potential_builtin_points_to(f, value, origin) or - not exists(global_variable(f)) and context.appliesToScope(f.getScope()) and + not exists(global_variable(f)) and + context.appliesToScope(f.getScope()) and potential_builtin_points_to(f, value, origin) ) } @@ -359,8 +380,10 @@ cached module PointsToInternal { } /** Holds if `f` is an attribute `x.attr` and points to `(value, cls, origin)`. */ - pragma [noinline] - private predicate attribute_load_points_to(AttrNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate attribute_load_points_to( + AttrNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { none() // TO DO -- Support CustomPointsToAttribute //or @@ -370,12 +393,16 @@ cached module PointsToInternal { //) } - /* Treat `ForNode` as intermediate step between sequence and iteration variable. + /* + * Treat `ForNode` as intermediate step between sequence and iteration variable. * In otherwords treat `for i in x:` as being equivalent to `i = next(iter(x))` * attaching the value of `next(iter(x))` to the `ForNode`. */ - pragma [noinline] - private predicate iteration_points_to(ForNode for, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + + pragma[noinline] + private predicate iteration_points_to( + ForNode for, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(ControlFlowNode seqNode, ObjectInternal seq | for.iterates(_, seqNode) and pointsTo(seqNode, context, seq, _) and @@ -385,7 +412,9 @@ cached module PointsToInternal { } /** Holds if the ESSA definition `def` refers to `(value, origin)` given the context `context`. */ - private predicate ssa_definition_points_to(EssaDefinition def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate ssa_definition_points_to( + EssaDefinition def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { ssa_phi_points_to(def, context, value, origin) or exists(ControlFlowNode orig | @@ -398,14 +427,18 @@ cached module PointsToInternal { ssa_node_refinement_points_to(def, context, value, origin) } - pragma [noinline] - private predicate ssa_node_definition_points_to(EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate ssa_node_definition_points_to( + EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { reachableBlock(def.getDefiningNode().getBasicBlock(), context) and ssa_node_definition_points_to_unpruned(def, context, value, origin) } - pragma [nomagic] - private predicate ssa_node_definition_points_to_unpruned(EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[nomagic] + private predicate ssa_node_definition_points_to_unpruned( + EssaNodeDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { InterProceduralPointsTo::parameter_points_to(def, context, value, origin) or assignment_points_to(def, context, value, origin) @@ -424,10 +457,13 @@ cached module PointsToInternal { /* * No points-to for non-local function entry definitions yet. */ - } - pragma [noinline] - private predicate ssa_node_refinement_points_to(EssaNodeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + } + + pragma[noinline] + private predicate ssa_node_refinement_points_to( + EssaNodeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { method_callsite_points_to(def, context, value, origin) or InterModulePointsTo::import_star_points_to(def, context, value, origin) @@ -442,20 +478,26 @@ cached module PointsToInternal { } /** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */ - private predicate method_callsite_points_to(MethodCallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate method_callsite_points_to( + MethodCallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { /* The value of self remains the same, only the attributes may change */ variablePointsTo(def.getInput(), context, value, origin) } /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attribute_delete_points_to(EssaAttributeDeletion def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attribute_delete_points_to( + EssaAttributeDeletion def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { variablePointsTo(def.getInput(), context, value, origin) } /** Attribute assignments have no effect as far as value tracking is concerned, except for `__class__`. */ - pragma [noinline] - private predicate attribute_assignment_points_to(AttributeAssignment def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attribute_assignment_points_to( + AttributeAssignment def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { def.getName() = "__class__" and exists(ObjectInternal cls | pointsTo(def.getValue(), context, cls, _) and @@ -464,30 +506,42 @@ cached module PointsToInternal { ) } - private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate self_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { origin = def.getDefiningNode() and value.(SelfInstanceInternal).parameterAndContext(def, context) } /** Holds if ESSA edge refinement, `def`, refers to `(value, cls, origin)`. */ - private predicate ssa_filter_definition_points_to(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + private predicate ssa_filter_definition_points_to( + PyEdgeRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(ControlFlowNode orig | def.getSense() = ssa_filter_definition_bool(def, context, value, orig) and origin = CfgOrigin::fromCfgNode(orig) ) } - private boolean ssa_filter_definition_bool(PyEdgeRefinement def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - result = Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, origin) + private boolean ssa_filter_definition_bool( + PyEdgeRefinement def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + result = + Conditionals::testEvaluates(def.getTest(), def.getInput().getASourceUse(), context, value, + origin) } /** Holds if ESSA definition, `unipi`, refers to `(value, origin)`. */ - pragma [noinline] - private predicate uni_edged_pi_points_to(SingleSuccessorGuard unipi, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate uni_edged_pi_points_to( + SingleSuccessorGuard unipi, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(ControlFlowNode test, ControlFlowNode use, ControlFlowNode orig | - /* Because calls such as `len` may create a new variable, we need to go via the source variable + /* + * Because calls such as `len` may create a new variable, we need to go via the source variable * That is perfectly safe as we are only dealing with calls that do not mutate their arguments. */ + unipi.useAndTest(use, test) and unipi.getSense() = Conditionals::testEvaluates(test, use, context, value, orig) and origin = CfgOrigin::fromCfgNode(orig) @@ -495,13 +549,18 @@ cached module PointsToInternal { } /** Points-to for normal assignments `def = ...`. */ - pragma [noinline] - private predicate assignment_points_to(AssignmentDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate assignment_points_to( + AssignmentDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { pointsTo(def.getValue(), context, value, origin) } - pragma [nomagic] - private predicate sequence_index_points_to(ControlFlowNode f, PointsToContext context, SequenceObjectInternal sequence, ObjectInternal value, int index) { + pragma[nomagic] + private predicate sequence_index_points_to( + ControlFlowNode f, PointsToContext context, SequenceObjectInternal sequence, + ObjectInternal value, int index + ) { pointsTo(f, context, sequence, _) and value = sequence.getItem(index) } @@ -525,18 +584,22 @@ cached module PointsToInternal { } /** Points-to for deletion: `del name`. */ - pragma [noinline] - private predicate delete_points_to(DeletionDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - value = ObjectInternal::undefined() and origin = def.getDefiningNode() and context.appliesToScope(def.getScope()) + pragma[noinline] + private predicate delete_points_to( + DeletionDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + value = ObjectInternal::undefined() and + origin = def.getDefiningNode() and + context.appliesToScope(def.getScope()) } /** Implicit "definition" of `__name__` at the start of a module. */ - pragma [noinline] - private predicate module_name_points_to(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate module_name_points_to( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { def.getVariable().getName() = "__name__" and - exists(Module m | - m = def.getScope() - | + exists(Module m | m = def.getScope() | value = module_dunder_name(m) and context.isImport() or value.strValue() = "__main__" and context.isMain() and context.appliesToScope(m) @@ -545,18 +608,16 @@ cached module PointsToInternal { } private ObjectInternal module_dunder_name(Module m) { - exists(string name | - result.strValue() = name | - if m.isPackageInit() then - name = m.getPackage().getName() - else - name = m.getName() + exists(string name | result.strValue() = name | + if m.isPackageInit() then name = m.getPackage().getName() else name = m.getName() ) } /** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */ - pragma [nomagic] - private predicate ssa_phi_points_to(PhiFunction phi, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + private predicate ssa_phi_points_to( + PhiFunction phi, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { exists(EssaVariable input | ssa_phi_reachable_from_input(phi, context, input) and variablePointsTo(input, context, value, origin) @@ -565,7 +626,9 @@ cached module PointsToInternal { /* Helper for ssa_phi_points_to */ cached - predicate ssa_phi_reachable_from_input(PhiFunction phi, PointsToContext context, EssaVariable input) { + predicate ssa_phi_reachable_from_input( + PhiFunction phi, PointsToContext context, EssaVariable input + ) { exists(BasicBlock pred | input = phi.getInput(pred) and reachableEdge(pred, phi.getBasicBlock(), context) @@ -573,8 +636,10 @@ cached module PointsToInternal { } /** Points-to for implicit variable declarations at scope-entry. */ - pragma [noinline] - private predicate scope_entry_points_to(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate scope_entry_points_to( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Transfer from another scope */ exists(EssaVariable var, PointsToContext outer, CfgOrigin orig | InterProceduralPointsTo::scope_entry_value_transfer(var, outer, def, context) and @@ -589,74 +654,91 @@ cached module PointsToInternal { builtin_not_in_outer_scope(def, context, value, origin) } - private predicate undefined_variable(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate undefined_variable( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(Scope scope | not def.getVariable().getName() = "__name__" and not def.getVariable().isMetaVariable() and - def.getScope() = scope and context.appliesToScope(scope) | + def.getScope() = scope and + context.appliesToScope(scope) + | def.getSourceVariable() instanceof GlobalVariable and scope instanceof Module or - def.getSourceVariable() instanceof LocalVariable and (context.isImport() or context.isRuntime() or context.isMain()) + def.getSourceVariable() instanceof LocalVariable and + (context.isImport() or context.isRuntime() or context.isMain()) ) and - value = ObjectInternal::undefined() and origin = def.getDefiningNode() + value = ObjectInternal::undefined() and + origin = def.getDefiningNode() } - private predicate builtin_not_in_outer_scope(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate builtin_not_in_outer_scope( + ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(Module mod, GlobalVariable var | var = def.getSourceVariable() and mod = def.getScope().getEnclosingModule() and context.appliesToScope(def.getScope()) and not exists(EssaVariable v | v.getSourceVariable() = var and v.getScope() = mod) and - value = ObjectInternal::builtin(var.getId()) and origin = def.getDefiningNode() + value = ObjectInternal::builtin(var.getId()) and + origin = def.getDefiningNode() ) } /** Holds if `f` is an expression node `tval if cond else fval` and points to `(value, origin)`. */ - private predicate if_exp_points_to(IfExprNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + private predicate if_exp_points_to( + IfExprNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { pointsTo(f.getAnOperand(), context, value, origin) } /* Holds if `import name` will import the module `m`. */ - cached predicate module_imported_as(ModuleObjectInternal m, string name) { + cached + predicate module_imported_as(ModuleObjectInternal m, string name) { /* Normal imports */ m.getName() = name or /* sys.modules['name'] = m */ exists(ControlFlowNode sys_modules_flow, ControlFlowNode n, ControlFlowNode mod | - /* Use previous points-to here to avoid slowing down the recursion too much */ - exists(SubscriptNode sub | - sub.getObject() = sys_modules_flow and - pointsTo(sys_modules_flow, _, ObjectInternal::sysModules(), _) and - sub.getIndex() = n and - n.getNode().(StrConst).getText() = name and - sub.(DefinitionNode).getValue() = mod and - pointsTo(mod, _, m, _) - ) + /* Use previous points-to here to avoid slowing down the recursion too much */ + exists(SubscriptNode sub | + sub.getObject() = sys_modules_flow and + pointsTo(sys_modules_flow, _, ObjectInternal::sysModules(), _) and + sub.getIndex() = n and + n.getNode().(StrConst).getText() = name and + sub.(DefinitionNode).getValue() = mod and + pointsTo(mod, _, m, _) + ) ) } - } private module InterModulePointsTo { - - pragma [noinline] - predicate import_points_to(ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate import_points_to( + ControlFlowNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(string name, ImportExpr i | - i.getAFlowNode() = f and i.getImportedModuleName() = name and + i.getAFlowNode() = f and + i.getImportedModuleName() = name and PointsToInternal::module_imported_as(value, name) and origin = f and context.appliesTo(f) ) } - predicate from_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate from_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { from_self_import_points_to(f, context, value, origin) or from_other_import_points_to(f, context, value, origin) } - pragma [noinline] - predicate from_self_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate from_self_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(EssaVariable var, CfgOrigin orig | var = ssa_variable_for_module_attribute(f, context) and PointsToInternal::variablePointsTo(var, context, value, orig) and @@ -664,8 +746,10 @@ private module InterModulePointsTo { ) } - pragma [noinline] - predicate from_other_import_points_to(ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate from_other_import_points_to( + ImportMemberNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(string name, ModuleObjectInternal mod, CfgOrigin orig | from_import_imports(f, context, mod, name) and (mod.getSourceModule() != f.getEnclosingModule() or mod.isBuiltin()) and @@ -674,48 +758,60 @@ private module InterModulePointsTo { ) or PointsToInternal::pointsTo(f.getModule(_), context, ObjectInternal::unknown(), _) and - value = ObjectInternal::unknown() and origin = f + value = ObjectInternal::unknown() and + origin = f } - private predicate from_import_imports(ImportMemberNode f, PointsToContext context, ModuleObjectInternal mod, string name) { + private predicate from_import_imports( + ImportMemberNode f, PointsToContext context, ModuleObjectInternal mod, string name + ) { PointsToInternal::pointsTo(f.getModule(name), context, mod, _) } - pragma [noinline] + pragma[noinline] private EssaVariable ssa_variable_for_module_attribute(ImportMemberNode f, PointsToContext context) { exists(string name, ModuleObjectInternal mod, Module m | - mod.getSourceModule() = m and m = result.getScope() and + mod.getSourceModule() = m and + m = result.getScope() and PointsToInternal::pointsTo(f.getModule(name), context, mod, _) and result = ssa_variable_for_module_attribute_helper(f, name, m) ) } - pragma [noinline] - private EssaVariable ssa_variable_for_module_attribute_helper(ImportMemberNode f, string name, Module m) { - result.getSourceVariable().getName() = name and result.getAUse() = f - and m = f.getEnclosingModule() + pragma[noinline] + private EssaVariable ssa_variable_for_module_attribute_helper( + ImportMemberNode f, string name, Module m + ) { + result.getSourceVariable().getName() = name and + result.getAUse() = f and + m = f.getEnclosingModule() } /* Helper for implicit_submodule_points_to */ private ModuleObjectInternal getModule(ImplicitSubModuleDefinition def) { - exists(PackageObjectInternal package | - package.getSourceModule() = def.getDefiningNode().getScope() and - result = package.submodule(def.getSourceVariable().getName()) - ) + exists(PackageObjectInternal package | + package.getSourceModule() = def.getDefiningNode().getScope() and + result = package.submodule(def.getSourceVariable().getName()) + ) } - /** Implicit "definition" of the names of submodules at the start of an `__init__.py` file. + /** + * Implicit "definition" of the names of submodules at the start of an `__init__.py` file. * * PointsTo isn't exactly how the interpreter works, but is the best approximation we can manage statically. */ - pragma [noinline] - predicate implicit_submodule_points_to(ImplicitSubModuleDefinition def, ModuleObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate implicit_submodule_points_to( + ImplicitSubModuleDefinition def, ModuleObjectInternal value, ControlFlowNode origin + ) { value = getModule(def) and origin = CfgOrigin::fromObject(value).asCfgNodeOrHere(def.getDefiningNode()) } /** Points-to for `from ... import *`. */ - predicate import_star_points_to(ImportStarRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { + predicate import_star_points_to( + ImportStarRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { /* Attribute from imported module */ exists(CfgOrigin orig, ImportStarNode imp, ModuleObjectInternal mod, string name | imp = def.getDefiningNode() and @@ -733,18 +829,22 @@ private module InterModulePointsTo { ) } - /** Holds if `def` is technically a definition of `var`, but the `from ... import *` does not in fact define `var`. */ - cached predicate variable_not_redefined_by_import_star(EssaVariable var, PointsToContext context, ImportStarRefinement def) { + cached + predicate variable_not_redefined_by_import_star( + EssaVariable var, PointsToContext context, ImportStarRefinement def + ) { var = def.getInput() and exists(ModuleObjectInternal mod | - PointsToInternal::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), context, mod, _) | + PointsToInternal::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), context, mod, _) + | moduleExportsBoolean(mod, var.getSourceVariable().getName()) = false or var.getSourceVariable().getName().charAt(0) = "_" or exists(Module m, string name | - m = mod.getSourceModule() and name = var.getSourceVariable().getName() | + m = mod.getSourceModule() and name = var.getSourceVariable().getName() + | not m.declaredInAll(_) and name.charAt(0) = "_" ) ) @@ -755,12 +855,10 @@ private module InterModulePointsTo { imp = def.getDefiningNode() and PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) and var = def.getVariable() - | - if var.isMetaVariable() then ( - ModuleAttributes::attributePointsTo(def.getInput().getDefinition(), name, _, _) - ) else ( - def.getVariable().getName() = name - ) + | + if var.isMetaVariable() + then ModuleAttributes::attributePointsTo(def.getInput().getDefinition(), name, _, _) + else def.getVariable().getName() = name ) or exists(PackageObjectInternal package | @@ -770,19 +868,16 @@ private module InterModulePointsTo { } private boolean pythonModuleExportsBoolean(PythonModuleObjectInternal mod, string name) { - exists(Module src | - src = mod.getSourceModule() - | + exists(Module src | src = mod.getSourceModule() | src.declaredInAll(name) and result = true or declared_all_is_simple(src) and not src.declaredInAll(name) and - ofInterestInExports(mod, name) and result = false + ofInterestInExports(mod, name) and + result = false or - (not src.declaredInAll(name) and not declared_all_is_simple(src)) - and - exists(ObjectInternal val | - ModuleAttributes::pointsToAtExit(src, name, val, _) | + (not src.declaredInAll(name) and not declared_all_is_simple(src)) and + exists(ObjectInternal val | ModuleAttributes::pointsToAtExit(src, name, val, _) | val = ObjectInternal::undefined() and result = false or val != ObjectInternal::undefined() and result = true @@ -793,23 +888,24 @@ private module InterModulePointsTo { /** Holds if __all__ is declared and not mutated */ private predicate declared_all_is_simple(Module m) { exists(AssignStmt a, GlobalVariable all | - a.defines(all) and a.getScope() = m and + a.defines(all) and + a.getScope() = m and all.getId() = "__all__" and - not exists(Attribute attr | - all.getALoad() = attr.getObject() - ) + not exists(Attribute attr | all.getALoad() = attr.getObject()) ) } private boolean packageExportsBoolean(PackageObjectInternal mod, string name) { - exists(Folder folder | - folder = mod.getFolder() | + exists(Folder folder | folder = mod.getFolder() | exportsSubmodule(folder, name) and result = true or - not exportsSubmodule(folder, name) and result = moduleExportsBoolean(mod.getInitModule(), name) + not exportsSubmodule(folder, name) and + result = moduleExportsBoolean(mod.getInitModule(), name) or - mod.hasNoInitModule() and not exportsSubmodule(folder, name) and - ofInterestInExports(mod, name) and result = false + mod.hasNoInitModule() and + not exportsSubmodule(folder, name) and + ofInterestInExports(mod, name) and + result = false ) } @@ -823,8 +919,7 @@ private module InterModulePointsTo { } boolean builtinModuleExportsBoolean(BuiltinModuleObjectInternal mod, string name) { - exists(Builtin bltn | - bltn = mod.getBuiltin() | + exists(Builtin bltn | bltn = mod.getBuiltin() | exists(bltn.getMember(name)) and result = true or ofInterestInExports(mod, name) and not exists(bltn.getMember(name)) and result = false @@ -841,29 +936,34 @@ private module InterModulePointsTo { result = builtinModuleExportsBoolean(mod, name) ) } - } module InterProceduralPointsTo { - - cached predicate call(CallNode call, PointsToContext caller, ObjectInternal value) { + cached + predicate call(CallNode call, PointsToContext caller, ObjectInternal value) { PointsToInternal::pointsTo(call.getFunction(), caller, value, _) } - cached predicate callWithContext(CallNode call, PointsToContext caller, ObjectInternal value, PointsToContext callee) { + cached + predicate callWithContext( + CallNode call, PointsToContext caller, ObjectInternal value, PointsToContext callee + ) { callee.fromCall(call, caller) and PointsToInternal::pointsTo(call.getFunction(), caller, value, _) } - pragma [noinline] - predicate call_points_to(CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate call_points_to( + CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Either not a decorator, or we understand the return value */ (value != ObjectInternal::unknown() or not f.isDecoratorCall()) and call_points_to_from_callee(f, context, value, origin) or f.isFunctionDecoratorCall() and call_points_to_from_callee(f, context, ObjectInternal::unknown(), _) and - value = TDecoratedFunction(f) and origin = f + value = TDecoratedFunction(f) and + origin = f or f.isClassDecoratorCall() and call_points_to_from_callee(f, context, ObjectInternal::unknown(), _) and @@ -876,11 +976,11 @@ module InterProceduralPointsTo { } /** Helper for call_points_to to improve join-order */ - pragma [noinline] - private predicate call_points_to_from_callee(CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { - exists(ObjectInternal func | - call(f, context, func) - | + pragma[noinline] + private predicate call_points_to_from_callee( + CallNode f, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { + exists(ObjectInternal func | call(f, context, func) | exists(CfgOrigin orig, PointsToContext callee | callee.fromCall(f, context) and func.callResult(callee, value, orig) and @@ -889,7 +989,8 @@ module InterProceduralPointsTo { or context.untrackableCall(f) and func.contextSensitiveCallee() and - value = ObjectInternal::unknown() and origin = f + value = ObjectInternal::unknown() and + origin = f or exists(CfgOrigin orig | func.callResult(value, orig) and @@ -900,8 +1001,10 @@ module InterProceduralPointsTo { } /** Points-to for parameter. `def foo(param): ...`. */ - pragma [noinline] - predicate parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { self_parameter_points_to(def, context, value, origin) or normal_parameter_points_to(def, context, value, origin) @@ -912,21 +1015,29 @@ module InterProceduralPointsTo { } /** Helper for `parameter_points_to` */ - pragma [noinline] - private predicate normal_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate normal_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(PointsToContext caller, ControlFlowNode arg | PointsToInternal::pointsTo(arg, caller, value, origin) and named_argument_transfer(arg, caller, def, context) ) or - not def.isSelf() and not def.isVarargs() and not def.isKwargs() and - context.isRuntime() and value = ObjectInternal::unknown() and origin = def.getDefiningNode() + not def.isSelf() and + not def.isVarargs() and + not def.isKwargs() and + context.isRuntime() and + value = ObjectInternal::unknown() and + origin = def.getDefiningNode() or positional_parameter_points_to(def, context, value, origin) } - pragma [noinline] - private predicate self_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate self_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { def.isSelf() and exists(CallNode call, BoundMethodObjectInternal method, Function func, PointsToContext caller | callWithContext(call, caller, method, context) and @@ -937,7 +1048,9 @@ module InterProceduralPointsTo { ) } - predicate selfMethodCall(SelfCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee) { + predicate selfMethodCall( + SelfCallsiteRefinement def, PointsToContext caller, Function func, PointsToContext callee + ) { def.getInput().getSourceVariable().(Variable).isSelf() and exists(PythonFunctionObjectInternal method, CallNode call | method.getScope() = func and @@ -948,14 +1061,16 @@ module InterProceduralPointsTo { } /** Helper for parameter_points_to */ - pragma [noinline] - private predicate default_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate default_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::importCtxPointsTo(def.getDefault(), value, origin) and context_for_default_value(def, context) } /** Helper for default_parameter_points_to */ - pragma [noinline] + pragma[noinline] private predicate context_for_default_value(ParameterDefinition def, PointsToContext context) { context.isRuntime() or @@ -970,8 +1085,10 @@ module InterProceduralPointsTo { } /** Helper for parameter_points_to */ - pragma [noinline] - private predicate special_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + private predicate special_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { /* Runtime: Just an unknown tuple (or dict for `**` args) */ special_parameter_value(def, value) and context.isRuntime() and @@ -996,11 +1113,15 @@ module InterProceduralPointsTo { origin = def.getDefiningNode() } - /** Holds if `call` in context `caller` calls into the function scope `scope` in context `callee` and + /** + * Holds if `call` in context `caller` calls into the function scope `scope` in context `callee` and * that the number of position arguments (including expansion of `*` argument) exceeds the number of positional arguments by * `length` and that the excess arguments start at `start`. */ - predicate varargs_tuple(CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int start, int length) { + predicate varargs_tuple( + CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int start, + int length + ) { exists(int parameter_offset | callsite_calls_function(call, caller, scope, callee, parameter_offset) and start = scope.getPositionalParameterCount() - parameter_offset and @@ -1013,7 +1134,8 @@ module InterProceduralPointsTo { predicate varargs_empty_tuple(Function func, PointsToContext callee) { exists(CallNode call, PointsToContext caller, int parameter_offset | callsite_calls_function(call, caller, func, callee, parameter_offset) and - func.getPositionalParameterCount() - parameter_offset >= positional_argument_count(call, caller) + func.getPositionalParameterCount() - parameter_offset >= + positional_argument_count(call, caller) ) } @@ -1024,23 +1146,28 @@ module InterProceduralPointsTo { p.isKwargs() and value = TUnknownInstance(ObjectInternal::builtin("dict")) } - /** Holds if the `n`th argument in call `call` with context `caller` points-to `value` from `origin`, including values in tuples + /** + * Holds if the `n`th argument in call `call` with context `caller` points-to `value` from `origin`, including values in tuples * expanded by a `*` argument. For example, for the call `f('a', *(`x`,`y`))` the arguments are `('a', 'x', y')` */ - predicate positional_argument_points_to(CallNode call, int n, PointsToContext caller, ObjectInternal value, ControlFlowNode origin) { + predicate positional_argument_points_to( + CallNode call, int n, PointsToContext caller, ObjectInternal value, ControlFlowNode origin + ) { PointsToInternal::pointsTo(call.getArg(n), caller, value, origin) or exists(SequenceObjectInternal arg, int pos | pos = call.getNode().getPositionalArgumentCount() and PointsToInternal::pointsTo(origin, caller, arg, _) and - value = arg.getItem(n-pos) and + value = arg.getItem(n - pos) and origin = call.getStarArg() ) } - /** Gets the number of positional arguments including values in tuples expanded by a `*` argument.*/ + /** Gets the number of positional arguments including values in tuples expanded by a `*` argument. */ private int positional_argument_count(CallNode call, PointsToContext caller) { - result = call.getNode().getPositionalArgumentCount() and not exists(call.getStarArg()) and caller.appliesTo(call) + result = call.getNode().getPositionalArgumentCount() and + not exists(call.getStarArg()) and + caller.appliesTo(call) or exists(SequenceObjectInternal arg, int pos | pos = call.getNode().getPositionalArgumentCount() and @@ -1050,19 +1177,25 @@ module InterProceduralPointsTo { } /** Holds if the parameter definition `def` points-to `value` from `origin` given the context `context` */ - predicate positional_parameter_points_to(ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + predicate positional_parameter_points_to( + ParameterDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin + ) { exists(CallNode call, int argument, PointsToContext caller, Function func, int offset | positional_argument_points_to(call, argument, caller, value, origin) and callsite_calls_function(call, caller, func, context, offset) and - def.getParameter() = func.getArg(argument+offset) + def.getParameter() = func.getArg(argument + offset) ) } /** Holds if the named `argument` given the context `caller` is transferred to the parameter `param` with conntext `callee` by a call. */ - cached predicate named_argument_transfer(ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, PointsToContext callee) { + cached + predicate named_argument_transfer( + ControlFlowNode argument, PointsToContext caller, ParameterDefinition param, + PointsToContext callee + ) { exists(CallNode call, Function func, int offset | callsite_calls_function(call, caller, func, callee, offset) - | + | exists(string name | argument = call.getArgByName(name) and param.getParameter() = func.getArgByName(name) @@ -1070,10 +1203,15 @@ module InterProceduralPointsTo { ) } - /** Holds if the `call` with context `caller` calls the function `scope` in context `callee` + /** + * Holds if the `call` with context `caller` calls the function `scope` in context `callee` * and the offset from argument to parameter is `parameter_offset` */ - cached predicate callsite_calls_function(CallNode call, PointsToContext caller, Function scope, PointsToContext callee, int parameter_offset) { + cached + predicate callsite_calls_function( + CallNode call, PointsToContext caller, Function scope, PointsToContext callee, + int parameter_offset + ) { exists(ObjectInternal func | callWithContext(call, caller, func, callee) and func.calleeAndOffset(scope, parameter_offset) @@ -1081,34 +1219,56 @@ module InterProceduralPointsTo { } /** Model the transfer of values at scope-entry points. Transfer from `(pred_var, pred_context)` to `(succ_def, succ_context)`. */ - cached predicate scope_entry_value_transfer(EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, PointsToContext succ_context) { + cached + predicate scope_entry_value_transfer( + EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, + PointsToContext succ_context + ) { scope_entry_value_transfer_from_earlier(pred_var, pred_context, succ_def, succ_context) or callsite_entry_value_transfer(pred_var, pred_context, succ_def, succ_context) or - pred_context.isImport() and pred_context = succ_context and + pred_context.isImport() and + pred_context = succ_context and class_entry_value_transfer(pred_var, succ_def) } - /** Helper for `scope_entry_value_transfer`. Transfer of values from a temporally earlier scope to later scope. - * Earlier and later scopes are, for example, a module and functions in that module, or an __init__ method and another method. */ - pragma [noinline] - private predicate scope_entry_value_transfer_from_earlier(EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, PointsToContext succ_context) { + /** + * Helper for `scope_entry_value_transfer`. Transfer of values from a temporally earlier scope to later scope. + * Earlier and later scopes are, for example, a module and functions in that module, or an __init__ method and another method. + */ + pragma[noinline] + private predicate scope_entry_value_transfer_from_earlier( + EssaVariable pred_var, PointsToContext pred_context, ScopeEntryDefinition succ_def, + PointsToContext succ_context + ) { exists(Scope pred_scope, Scope succ_scope | BaseFlow::scope_entry_value_transfer_from_earlier(pred_var, pred_scope, succ_def, succ_scope) and succ_context.appliesToScope(succ_scope) - | + | succ_context.isRuntime() and succ_context = pred_context or - pred_context.isImport() and pred_scope instanceof ImportTimeScope and - (succ_context.fromRuntime() or - /* A call made at import time, but from another module. Assume this module has been fully imported. */ - succ_context.isCall() and exists(CallNode call | succ_context.fromCall(call, _) and call.getEnclosingModule() != pred_scope)) + pred_context.isImport() and + pred_scope instanceof ImportTimeScope and + ( + succ_context.fromRuntime() + or + /* A call made at import time, but from another module. Assume this module has been fully imported. */ + succ_context.isCall() and + exists(CallNode call | + succ_context.fromCall(call, _) and call.getEnclosingModule() != pred_scope + ) + ) or - /* If predecessor scope is main, then we assume that any global defined exactly once + /* + * If predecessor scope is main, then we assume that any global defined exactly once * is available to all functions. Although not strictly true, this gives less surprising - * results in practice. */ - pred_context.isMain() and pred_scope instanceof Module and succ_context.fromRuntime() and + * results in practice. + */ + + pred_context.isMain() and + pred_scope instanceof Module and + succ_context.fromRuntime() and exists(Variable v | v = pred_var.getSourceVariable() and not strictcount(v.getAStore()) > 1 @@ -1116,16 +1276,23 @@ module InterProceduralPointsTo { ) or exists(NonEscapingGlobalVariable var | - var = pred_var.getSourceVariable() and var = succ_def.getSourceVariable() and - pred_var.getAUse() = succ_context.getRootCall() and pred_context.isImport() and + var = pred_var.getSourceVariable() and + var = succ_def.getSourceVariable() and + pred_var.getAUse() = succ_context.getRootCall() and + pred_context.isImport() and succ_context.appliesToScope(succ_def.getScope()) ) } - /** Helper for `scope_entry_value_transfer`. - * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. */ - pragma [noinline] - private predicate callsite_entry_value_transfer(EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, PointsToContext callee) { + /** + * Helper for `scope_entry_value_transfer`. + * Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. + */ + pragma[noinline] + private predicate callsite_entry_value_transfer( + EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, + PointsToContext callee + ) { exists(ControlFlowNode use, SsaSourceVariable var | var_and_use(caller_var, use, var) and entry_def.getSourceVariable() = var and @@ -1148,15 +1315,18 @@ module InterProceduralPointsTo { ) } - /** Points-to for a variable (possibly) redefined by a call: + /** + * Points-to for a variable (possibly) redefined by a call: * `var = ...; foo(); use(var)` * Where var may be redefined in call to `foo` if `var` escapes (is global or non-local). */ - pragma [noinline] - predicate callsite_points_to(CallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin) { - exists(SsaSourceVariable srcvar | - srcvar = def.getSourceVariable() | - if srcvar instanceof EscapingAssignmentGlobalVariable then ( + pragma[noinline] + predicate callsite_points_to( + CallsiteRefinement def, PointsToContext context, ObjectInternal value, CfgOrigin origin + ) { + exists(SsaSourceVariable srcvar | srcvar = def.getSourceVariable() | + if srcvar instanceof EscapingAssignmentGlobalVariable + then /* If global variable can be reassigned, we need to track it through calls */ exists(EssaVariable var, Function func, PointsToContext callee | callsite_calls_function(def.getCall(), context, func, callee, _) and @@ -1169,10 +1339,9 @@ module InterProceduralPointsTo { exists(callable.getBuiltin()) and PointsToInternal::variablePointsTo(def.getInput(), context, value, origin) ) - ) else ( + else /* Otherwise we can assume its value (but not those of its attributes or members) has not changed. */ PointsToInternal::variablePointsTo(def.getInput(), context, value, origin) - ) ) } @@ -1184,29 +1353,36 @@ module InterProceduralPointsTo { BaseFlow::reaches_exit(evar) } - /** INTERNAL -- Use `FunctionObject.neverReturns()` instead. + /** + * INTERNAL -- Use `FunctionObject.neverReturns()` instead. * Whether function `func` never returns. Slightly conservative approximation, this predicate may be false - * for a function that can never return. */ - cached predicate neverReturns(Function f) { - /* A Python function never returns if it has no normal exits that are not dominated by a + * for a function that can never return. + */ + cached + predicate neverReturns(Function f) { + /* + * A Python function never returns if it has no normal exits that are not dominated by a * call to a function which itself never returns. */ - forall(BasicBlock exit | - exit = f.getANormalExit().getBasicBlock() | - exists(FunctionObject callee, BasicBlock call | + + forall(BasicBlock exit | exit = f.getANormalExit().getBasicBlock() | + exists(FunctionObject callee, BasicBlock call | callee.getACall().getBasicBlock() = call and callee.neverReturns() and call.dominates(exit) ) ) } - } /** Gets the `value, origin` that `f` would refer to if it has not been assigned some other value */ -pragma [noinline] -private predicate potential_builtin_points_to(NameNode f, ObjectInternal value, ControlFlowNode origin) { - f.isGlobal() and f.isLoad() and origin = f and +pragma[noinline] +private predicate potential_builtin_points_to( + NameNode f, ObjectInternal value, ControlFlowNode origin +) { + f.isGlobal() and + f.isLoad() and + origin = f and ( value = ObjectInternal::builtin(f.getId()) or @@ -1214,20 +1390,23 @@ private predicate potential_builtin_points_to(NameNode f, ObjectInternal value, ) } - module Expressions { - - pragma [noinline] - private predicate attributeObjectPointsto(AttrNode attr, PointsToContext context, string name, ControlFlowNode obj, ObjectInternal objvalue) { - attr.isLoad() and attr.getObject(name) = obj and + pragma[noinline] + private predicate attributeObjectPointsto( + AttrNode attr, PointsToContext context, string name, ControlFlowNode obj, + ObjectInternal objvalue + ) { + attr.isLoad() and + attr.getObject(name) = obj and PointsToInternal::pointsTo(obj, context, objvalue, _) } - pragma [noinline] - predicate attributePointsTo(AttrNode attr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode obj, ObjectInternal objvalue) { - exists(string name | - attributeObjectPointsto(attr, context, name, obj, objvalue) - | + pragma[noinline] + predicate attributePointsTo( + AttrNode attr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode obj, ObjectInternal objvalue + ) { + exists(string name | attributeObjectPointsto(attr, context, name, obj, objvalue) | exists(CfgOrigin orig | objvalue.attribute(name, value, orig) and origin = orig.asCfgNodeOrHere(attr) @@ -1239,11 +1418,12 @@ module Expressions { ) } - pragma [noinline] - predicate subscriptPointsTo(SubscriptNode subscr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode obj, ObjectInternal objvalue) { - exists(ControlFlowNode index | - subscriptObjectAndIndex(subscr, context, obj, objvalue, index) - | + pragma[noinline] + predicate subscriptPointsTo( + SubscriptNode subscr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode obj, ObjectInternal objvalue + ) { + exists(ControlFlowNode index | subscriptObjectAndIndex(subscr, context, obj, objvalue, index) | objvalue.subscriptUnknown() and value = ObjectInternal::unknown() or @@ -1255,25 +1435,35 @@ module Expressions { origin = subscr } - predicate subscriptPartsPointsTo(SubscriptNode subscr, PointsToContext context, ObjectInternal objvalue, ObjectInternal indexvalue) { + predicate subscriptPartsPointsTo( + SubscriptNode subscr, PointsToContext context, ObjectInternal objvalue, + ObjectInternal indexvalue + ) { exists(ControlFlowNode index | subscriptObjectAndIndex(subscr, context, _, objvalue, index) and PointsToInternal::pointsTo(index, context, indexvalue, _) ) } - pragma [noinline] - private predicate subscriptObjectAndIndex(SubscriptNode subscr, PointsToContext context, ControlFlowNode obj, ObjectInternal objvalue, ControlFlowNode index) { + pragma[noinline] + private predicate subscriptObjectAndIndex( + SubscriptNode subscr, PointsToContext context, ControlFlowNode obj, ObjectInternal objvalue, + ControlFlowNode index + ) { subscr.isLoad() and obj = subscr.getObject() and PointsToInternal::pointsTo(obj, context, objvalue, _) and index = subscr.getIndex() } - /** Tracking too many binary expressions is likely to kill performance, so just say anything other than addition or bitwise or is 'unknown'. + /** + * Tracking too many binary expressions is likely to kill performance, so just say anything other than addition or bitwise or is 'unknown'. */ - pragma [noinline] - predicate binaryPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate binaryPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and operand = genericBinaryOperand(b) and PointsToInternal::pointsTo(operand, context, opvalue, _) and @@ -1285,34 +1475,40 @@ module Expressions { b.operands(result, op, _) or b.operands(_, op, result) - | + | not op instanceof BitOr and not op instanceof Add ) } - pragma [noinline] - predicate addPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate addPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and exists(Operator op | b.operands(operand, op, _) or b.operands(_, op, operand) - | + | op instanceof Add and PointsToInternal::pointsTo(operand, context, opvalue, _) and value = TUnknownInstance(opvalue.getClass()) ) } - pragma [noinline] - predicate bitOrPointsTo(BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate bitOrPointsTo( + BinaryExprNode b, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { origin = b and exists(Operator op, ControlFlowNode other | b.operands(operand, op, other) or b.operands(other, op, operand) - | + | op instanceof BitOr and exists(ObjectInternal obj, int i1, int i2 | pointsToInt(operand, context, opvalue, i1) and @@ -1327,13 +1523,16 @@ module Expressions { value = obj.intValue() } - pragma [noinline] - predicate unaryPointsTo(UnaryExprNode u, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + predicate unaryPointsTo( + UnaryExprNode u, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode operand, ObjectInternal opvalue + ) { exists(Unaryop op | op = u.getNode().getOp() and operand = u.getOperand() and PointsToInternal::pointsTo(operand, context, opvalue, _) - | + | op instanceof Not and value = ObjectInternal::bool(opvalue.booleanValue().booleanNot()) or op instanceof USub and value = ObjectInternal::fromInt(-opvalue.intValue()) @@ -1343,12 +1542,16 @@ module Expressions { origin = u } - pragma [noinline] - predicate builtinCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + predicate builtinCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { PointsToInternal::pointsTo(arg, context, argvalue, _) and arg = call.getArg(0) and exists(BuiltinFunctionObjectInternal callable | - PointsToInternal::pointsTo(call.getFunction(), context, callable, _) | + PointsToInternal::pointsTo(call.getFunction(), context, callable, _) + | callable != ObjectInternal::builtin("len") and callable != ObjectInternal::builtin("callable") and callable != ObjectInternal::builtin("isinstance") and @@ -1360,31 +1563,36 @@ module Expressions { origin = call } - pragma [noinline] - predicate typeCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + predicate typeCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { type_call1(call, arg, context, argvalue) and value = argvalue.getClass() and origin = CfgOrigin::fromObject(value).asCfgNodeOrHere(call) } - pragma [noinline] - private predicate lenCallPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { + pragma[noinline] + private predicate lenCallPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { len_call(call, arg, context, argvalue) and origin = call and - exists(int len | - len = argvalue.length() - | + exists(int len | len = argvalue.length() | value = TInt(len) and len >= 0 or len < 0 and value = TUnknownInstance(ObjectInternal::builtin("int")) ) } - pragma [noinline] - private predicate getattrPointsTo(CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode arg, ObjectInternal argvalue) { - exists(string name | - getattr_call(call, arg, context, argvalue, name) - | + pragma[noinline] + private predicate getattrPointsTo( + CallNode call, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode arg, ObjectInternal argvalue + ) { + exists(string name | getattr_call(call, arg, context, argvalue, name) | argvalue.attributesUnknown() and value = ObjectInternal::unknown() and origin = call or exists(CfgOrigin valOrigin | @@ -1393,8 +1601,10 @@ module Expressions { ) } - pragma [noinline] - predicate getattr_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name) { + pragma[noinline] + predicate getattr_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name + ) { exists(ControlFlowNode arg1 | call_and_args_for_getattr(call, context, use, arg1) and PointsToInternal::pointsTo(use, context, val, _) and @@ -1403,15 +1613,20 @@ module Expressions { } pragma[noinline] - private predicate call_and_args_for_getattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1) { + private predicate call_and_args_for_getattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1 + ) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("getattr"), _) ) } - pragma [noinline] - predicate setattr_call(CallNode call, PointsToContext context, ControlFlowNode obj, string name, ObjectInternal val, ControlFlowNode origin) { + pragma[noinline] + predicate setattr_call( + CallNode call, PointsToContext context, ControlFlowNode obj, string name, ObjectInternal val, + ControlFlowNode origin + ) { exists(ControlFlowNode arg1, ControlFlowNode arg2 | call_and_args_for_setattr(call, context, obj, arg1, arg2) and PointsToInternal::pointsTo(arg2, context, val, origin) and @@ -1420,29 +1635,37 @@ module Expressions { } pragma[noinline] - private predicate call_and_args_for_setattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1, ControlFlowNode arg2) { + private predicate call_and_args_for_setattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1, + ControlFlowNode arg2 + ) { exists(ControlFlowNode func | call3(call, func, arg0, arg1, arg2) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("setattr"), _) ) } - pragma [noinline] - private boolean containsComparisonEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean containsComparisonEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { exists(Cmpop op | comp.operands(operand, op, _) or comp.operands(_, op, operand) - | + | (op instanceof In or op instanceof NotIn) and PointsToInternal::pointsTo(operand, context, opvalue, _) - ) and result = maybe() + ) and + result = maybe() } - pragma [noinline] - private boolean equalityEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean equalityEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { exists(ObjectInternal other, boolean sense | equalityTest(comp, context, operand, opvalue, other, sense) - | + | other = opvalue and result = sense or other != opvalue and result = sense.booleanNot() @@ -1453,16 +1676,21 @@ module Expressions { ) } - pragma [noinline] - private boolean comparesToUnknown(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue) { + pragma[noinline] + private boolean comparesToUnknown( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue + ) { (comp.operands(operand, _, _) or comp.operands(_, _, operand)) and PointsToInternal::pointsTo(operand, context, opvalue, _) and opvalue = ObjectInternal::unknown() and result = maybe() } - pragma [noinline] - private predicate equalityTest(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, ObjectInternal other, boolean sense) { + pragma[noinline] + private predicate equalityTest( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, + ObjectInternal other, boolean sense + ) { exists(ControlFlowNode r | equality_test(comp, operand, sense, r) and PointsToInternal::pointsTo(operand, context, opvalue, _) and @@ -1470,11 +1698,13 @@ module Expressions { ) } - pragma [noinline] - private boolean inequalityEvaluatesTo(CompareNode comp, PointsToContext context, ControlFlowNode use, ObjectInternal val) { + pragma[noinline] + private boolean inequalityEvaluatesTo( + CompareNode comp, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { exists(boolean strict, boolean sense, ObjectInternal other | inequalityTest(comp, context, use, val, other, strict, sense) - | + | compare(val, other) = -1 and result = sense or compare(val, other) = 0 and result = strict.booleanNot() @@ -1509,11 +1739,9 @@ module Expressions { val.strValue() = other.strValue() and result = 0 } - pragma [nomagic] + pragma[nomagic] private int compare_sequence(SequenceObjectInternal val, SequenceObjectInternal other, int n) { - exists(int vlen, int olen | - sequence_lengths_in_comparison(val, other, vlen, olen) - | + exists(int vlen, int olen | sequence_lengths_in_comparison(val, other, vlen, olen) | n = vlen and olen > n and result = -1 or n = olen and vlen > n and result = 1 @@ -1523,35 +1751,43 @@ module Expressions { or result != 0 and result = compare_item(val, other, n) or - compare_item(val, other, n) = 0 and result = compare_sequence(val, other, n+1) + compare_item(val, other, n) = 0 and result = compare_sequence(val, other, n + 1) } - private predicate sequence_lengths_in_comparison(SequenceObjectInternal val, SequenceObjectInternal other, int vlen, int olen) { + private predicate sequence_lengths_in_comparison( + SequenceObjectInternal val, SequenceObjectInternal other, int vlen, int olen + ) { inequalityTest(_, _, _, val, other, _, _) and - vlen = val.length() and olen = other.length() + vlen = val.length() and + olen = other.length() } - pragma [noinline] + pragma[noinline] private int compare_item(SequenceObjectInternal val, SequenceObjectInternal other, int n) { inequalityTest(_, _, _, val, other, _, _) and result = compare_unbound(val.getItem(n), other.getItem(n)) } - pragma [noinline] - private predicate inequalityTest(CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, ObjectInternal other, boolean strict, boolean sense) { + pragma[noinline] + private predicate inequalityTest( + CompareNode comp, PointsToContext context, ControlFlowNode operand, ObjectInternal opvalue, + ObjectInternal other, boolean strict, boolean sense + ) { exists(ControlFlowNode r | inequality(comp, operand, r, strict) and sense = true or inequality(comp, r, operand, strict) and sense = false - | + | PointsToInternal::pointsTo(operand, context, opvalue, _) and PointsToInternal::pointsTo(r, context, other, _) ) } /** Helper for comparisons. */ - pragma [noinline] - private predicate inequality(CompareNode cmp, ControlFlowNode lesser, ControlFlowNode greater, boolean strict) { + pragma[noinline] + private predicate inequality( + CompareNode cmp, ControlFlowNode lesser, ControlFlowNode greater, boolean strict + ) { exists(Cmpop op | cmp.operands(lesser, op, greater) and op.getSymbol() = "<" and strict = true or @@ -1563,7 +1799,10 @@ module Expressions { ) } - predicate pointsTo(ControlFlowNode expr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, ControlFlowNode subexpr, ObjectInternal subvalue) { + predicate pointsTo( + ControlFlowNode expr, PointsToContext context, ObjectInternal value, ControlFlowNode origin, + ControlFlowNode subexpr, ObjectInternal subvalue + ) { attributePointsTo(expr, context, value, origin, subexpr, subvalue) or subscriptPointsTo(expr, context, value, origin, subexpr, subvalue) @@ -1587,8 +1826,10 @@ module Expressions { value = ObjectInternal::bool(evaluatesTo(expr, context, subexpr, subvalue)) and origin = expr } - pragma [noinline] - boolean evaluatesTo(ControlFlowNode expr, PointsToContext context, ControlFlowNode subexpr, ObjectInternal subvalue) { + pragma[noinline] + boolean evaluatesTo( + ControlFlowNode expr, PointsToContext context, ControlFlowNode subexpr, ObjectInternal subvalue + ) { result = equalityEvaluatesTo(expr, context, subexpr, subvalue) or result = inequalityEvaluatesTo(expr, context, subexpr, subvalue) @@ -1606,10 +1847,11 @@ module Expressions { result = hasattrEvaluatesTo(expr, context, subexpr, subvalue) } - pragma [nomagic] - private boolean isinstanceEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(ObjectInternal cls | - isinstance_call(call, use, context, val, cls) | + pragma[nomagic] + private boolean isinstanceEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(ObjectInternal cls | isinstance_call(call, use, context, val, cls) | result = Types::improperSubclass(val.getClass(), cls) or val = ObjectInternal::unknown() and result = maybe() @@ -1620,8 +1862,10 @@ module Expressions { ) } - private - predicate isinstance_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) { + private predicate isinstance_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ObjectInternal cls + ) { exists(ControlFlowNode func, ControlFlowNode arg1 | call2(call, func, use, arg1) and points_to_isinstance(func, context) and @@ -1630,8 +1874,10 @@ module Expressions { ) } - private - predicate issubclass_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, ObjectInternal cls) { + private predicate issubclass_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ObjectInternal cls + ) { exists(ControlFlowNode func, ControlFlowNode arg1 | call2(call, func, use, arg1) and points_to_issubclass(func, context) and @@ -1650,26 +1896,34 @@ module Expressions { PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("issubclass"), _) } - private predicate callable_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate callable_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("callable"), _) and use = call.getArg(0) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate len_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate len_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("len"), _) and use = call.getArg(0) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate type_call1(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val) { + private predicate type_call1( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val + ) { PointsToInternal::pointsTo(call.getFunction(), context, ObjectInternal::builtin("type"), _) and use = call.getArg(0) and not exists(call.getArg(1)) and PointsToInternal::pointsTo(use, context, val, _) } - private predicate hasattr_call(CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name) { + private predicate hasattr_call( + CallNode call, ControlFlowNode use, PointsToContext context, ObjectInternal val, string name + ) { exists(ControlFlowNode arg1 | call_to_hasattr(call, context, use, arg1) and PointsToInternal::pointsTo(use, context, val, _) and @@ -1678,17 +1932,20 @@ module Expressions { } pragma[noinline] - private predicate call_to_hasattr(ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1) { + private predicate call_to_hasattr( + ControlFlowNode call, PointsToContext context, ControlFlowNode arg0, ControlFlowNode arg1 + ) { exists(ControlFlowNode func | call2(call, func, arg0, arg1) and PointsToInternal::pointsTo(func, context, ObjectInternal::builtin("hasattr"), _) ) } - pragma [nomagic] - private boolean issubclassEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(ObjectInternal cls | - issubclass_call(call, use, context, val, cls) | + pragma[nomagic] + private boolean issubclassEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(ObjectInternal cls | issubclass_call(call, use, context, val, cls) | result = Types::improperSubclass(val, cls) or val = ObjectInternal::unknownClass() and result = maybe() @@ -1701,8 +1958,10 @@ module Expressions { ) } - pragma [noinline] - private boolean callableEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { + pragma[noinline] + private boolean callableEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { callable_call(call, use, context, val) and ( val = ObjectInternal::unknown() and result = maybe() @@ -1713,11 +1972,11 @@ module Expressions { ) } - pragma [noinline] - private boolean hasattrEvaluatesTo(CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val) { - exists(string name | - hasattr_call(call, use, context, val, name) - | + pragma[noinline] + private boolean hasattrEvaluatesTo( + CallNode call, PointsToContext context, ControlFlowNode use, ObjectInternal val + ) { + exists(string name | hasattr_call(call, use, context, val, name) | val = ObjectInternal::unknown() and result = maybe() or val = ObjectInternal::unknownClass() and result = maybe() @@ -1736,7 +1995,7 @@ module Expressions { isinstance_call(_, _, _, val, sup_or_tuple) and sub = val.getClass() ) - | + | sup = sup_or_tuple or sup = sup_or_tuple.(TupleObjectInternal).getItem(_) @@ -1745,28 +2004,32 @@ module Expressions { predicate requireHasAttr(ClassObjectInternal cls, string name) { cls != ObjectInternal::unknownClass() and - exists(ObjectInternal val | - val.getClass() = cls | + exists(ObjectInternal val | val.getClass() = cls | name = "__call__" and callable_call(_, _, _, val) or hasattr_call(_, _, _, val, name) ) } - } - module Conditionals { - - boolean testEvaluates(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal value, ControlFlowNode origin) { + boolean testEvaluates( + ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal value, + ControlFlowNode origin + ) { pinode_test(expr, use) and result = evaluates(expr, use, context, value, origin).booleanValue() } - pragma [noinline] - ObjectInternal evaluates(ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val, ControlFlowNode origin) { + pragma[noinline] + ObjectInternal evaluates( + ControlFlowNode expr, ControlFlowNode use, PointsToContext context, ObjectInternal val, + ControlFlowNode origin + ) { PointsToInternal::pointsTo(use, context, val, origin) and - pinode_test(_, use) and expr = use and result = val + pinode_test(_, use) and + expr = use and + result = val or exists(ControlFlowNode part, ObjectInternal partval | pinode_test_part(expr, part) and @@ -1793,18 +2056,17 @@ module Conditionals { inner.getAChild*() = use ) } - } -cached module Types { - - cached int base_count(ClassObjectInternal cls) { +cached +module Types { + cached + int base_count(ClassObjectInternal cls) { cls = ObjectInternal::builtin("object") and result = 0 or exists(cls.getBuiltin()) and cls != ObjectInternal::builtin("object") and result = 1 or - exists(Class pycls | - pycls = cls.(PythonClassObjectInternal).getScope() | + exists(Class pycls | pycls = cls.(PythonClassObjectInternal).getScope() | result = strictcount(pycls.getABase()) or isNewStyle(cls) and not exists(pycls.getABase()) and result = 1 @@ -1813,33 +2075,35 @@ cached module Types { ) } - cached ObjectInternal getBase(ClassObjectInternal cls, int n) { + cached + ObjectInternal getBase(ClassObjectInternal cls, int n) { result.getBuiltin() = cls.getBuiltin().getBaseClass() and n = 0 or - exists(Class pycls | - pycls = cls.(PythonClassObjectInternal).getScope() - | + exists(Class pycls | pycls = cls.(PythonClassObjectInternal).getScope() | exists(ObjectInternal base | PointsToInternal::pointsTo(pycls.getBase(n).getAFlowNode(), _, base, _) - | + | result = base and base != ObjectInternal::unknown() or base = ObjectInternal::unknown() and result = ObjectInternal::unknownClass() ) or - not exists(pycls.getABase()) and n = 0 and - isNewStyle(cls) and result = ObjectInternal::builtin("object") + not exists(pycls.getABase()) and + n = 0 and + isNewStyle(cls) and + result = ObjectInternal::builtin("object") ) or - cls = ObjectInternal::unknownClass() and n = 0 and + cls = ObjectInternal::unknownClass() and + n = 0 and result = ObjectInternal::builtin("object") } - cached predicate isOldStyle(ClassObjectInternal cls) { - newStylePython2(cls, 0) = false - } + cached + predicate isOldStyle(ClassObjectInternal cls) { newStylePython2(cls, 0) = false } - cached predicate isNewStyle(ClassObjectInternal cls) { + cached + predicate isNewStyle(ClassObjectInternal cls) { major_version() = 3 or cls.isBuiltin() @@ -1853,23 +2117,26 @@ cached module Types { hasDeclaredMetaclass(cls) = false and exists(Class pycls | pycls = cls.getClassDeclaration().getClass() and - n = count(pycls.getABase()) and result = false + n = count(pycls.getABase()) and + result = false ) or - exists(ClassObjectInternal base | - base = getBase(cls, n) | + exists(ClassObjectInternal base | base = getBase(cls, n) | hasDeclaredMetaclass(cls) = false and - isOldStyle(base) and result = newStylePython2(cls, n+1) + isOldStyle(base) and + result = newStylePython2(cls, n + 1) or isNewStyle(base) and result = true ) or getMro(declaredMetaClass(cls)).contains(ObjectInternal::type()) and - n = 0 and result = true + n = 0 and + result = true ) } - cached ClassList getMro(ClassObjectInternal cls) { + cached + ClassList getMro(ClassObjectInternal cls) { isNewStyle(cls) and result = Mro::newStyleMro(cls) or @@ -1877,8 +2144,12 @@ cached module Types { result = Mro::oldStyleMro(cls) } - cached predicate declaredAttribute(ClassObjectInternal cls, string name, ObjectInternal value, CfgOrigin origin) { - value = ObjectInternal::fromBuiltin(cls.getBuiltin().getMember(name)) and origin = CfgOrigin::unknown() + cached + predicate declaredAttribute( + ClassObjectInternal cls, string name, ObjectInternal value, CfgOrigin origin + ) { + value = ObjectInternal::fromBuiltin(cls.getBuiltin().getMember(name)) and + origin = CfgOrigin::unknown() or value != ObjectInternal::undefined() and exists(EssaVariable var | @@ -1888,7 +2159,8 @@ cached module Types { ) } - cached ClassObjectInternal getMetaClass(PythonClassObjectInternal cls) { + cached + ClassObjectInternal getMetaClass(PythonClassObjectInternal cls) { result = declaredMetaClass(cls) or hasDeclaredMetaclass(cls) = false and result = getInheritedMetaclass(cls) @@ -1896,7 +2168,8 @@ cached module Types { private ClassObjectInternal declaredMetaClass(PythonClassObjectInternal cls) { exists(ObjectInternal obj | - PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) | + PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) + | result = obj or obj = ObjectInternal::unknown() and result = ObjectInternal::unknownClass() @@ -1920,7 +2193,7 @@ cached module Types { exists(ControlFlowNode callee, ObjectInternal func | callee = decorator_call_callee(cls) and PointsToInternal::pointsTo(callee, _, func, _) - | + | func = six_add_metaclass_function() and result = true or func != six_add_metaclass_function() and result = false @@ -1937,7 +2210,8 @@ cached module Types { private boolean has_metaclass_var_metaclass(PythonClassObjectInternal cls) { exists(ObjectInternal obj | - PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) | + PointsToInternal::variablePointsTo(metaclass_var(cls.getScope()), _, obj, _) + | obj = ObjectInternal::undefined() and result = false or obj != ObjectInternal::undefined() and result = true @@ -1945,29 +2219,37 @@ cached module Types { or exists(Class pycls | pycls = cls.getScope() and - not exists(metaclass_var(pycls)) and result = false + not exists(metaclass_var(pycls)) and + result = false ) } private EssaVariable metaclass_var(Class cls) { result.getASourceUse() = cls.getMetaClass().getAFlowNode() or - major_version() = 2 and not exists(cls.getMetaClass()) and + major_version() = 2 and + not exists(cls.getMetaClass()) and result.getName() = "__metaclass__" and cls.(ImportTimeScope).entryEdge(result.getAUse(), _) } - cached predicate six_add_metaclass(CallNode decorator_call, PointsToContext context, ClassObjectInternal decorated, ControlFlowNode metaclass) { + cached + predicate six_add_metaclass( + CallNode decorator_call, PointsToContext context, ClassObjectInternal decorated, + ControlFlowNode metaclass + ) { exists(CallNode decorator | PointsToInternal::pointsTo(decorator_call.getArg(0), context, decorated, _) and decorator = decorator_call.getFunction() and - decorator.getArg(0) = metaclass | + decorator.getArg(0) = metaclass + | PointsToInternal::pointsTo(decorator.getFunction(), context, six_add_metaclass_function(), _) or exists(ModuleObjectInternal six | - six.getName() = "six" and - PointsToInternal::pointsTo(decorator.getFunction().(AttrNode).getObject("add_metaclass"), context, six, _) - ) + six.getName() = "six" and + PointsToInternal::pointsTo(decorator.getFunction().(AttrNode).getObject("add_metaclass"), + context, six, _) + ) ) } @@ -1978,7 +2260,7 @@ cached module Types { ) } - pragma [nomagic] + pragma[nomagic] private ClassObjectInternal getInheritedMetaclass(ClassObjectInternal cls) { result = getInheritedMetaclass(cls, 0) or @@ -1988,8 +2270,7 @@ cached module Types { /* Helper for getInheritedMetaclass */ private predicate hasUnknownBase(ClassObjectInternal cls) { - exists(ObjectInternal base | - base = getBase(cls, _) | + exists(ObjectInternal base | base = getBase(cls, _) | base.isClass() = false or base = ObjectInternal::unknownClass() @@ -1999,21 +2280,23 @@ cached module Types { private ClassObjectInternal getInheritedMetaclass(ClassObjectInternal cls, int n) { exists(Class c | c = cls.(PythonClassObjectInternal).getScope() and - n = count(c.getABase()) and n != 1 - | + n = count(c.getABase()) and + n != 1 + | result = ObjectInternal::type() and major_version() = 3 or result = ObjectInternal::classType() and major_version() = 2 ) or - base_count(cls) = 1 and n = 0 and + base_count(cls) = 1 and + n = 0 and result = getBase(cls, 0).getClass() or exists(ClassObjectInternal meta1, ClassObjectInternal meta2 | base_count(cls) > 1 and meta1 = getBase(cls, n).getClass() and - meta2 = getInheritedMetaclass(cls, n+1) - | + meta2 = getInheritedMetaclass(cls, n + 1) + | /* Choose sub-class */ improperSuperType(meta1) = meta2 and result = meta1 or @@ -2035,7 +2318,8 @@ cached module Types { } /* Holds if type inference failed to compute the full class hierarchy for this class for the reason given. */ - cached predicate failedInference(ClassObjectInternal cls, string reason) { + cached + predicate failedInference(ClassObjectInternal cls, string reason) { exists(int priority | failedInference(cls, reason, priority) and priority = max(int p | failedInference(cls, _, p)) @@ -2044,41 +2328,60 @@ cached module Types { /* Holds if type inference failed to compute the full class hierarchy for this class for the reason given. */ private predicate failedInference(ClassObjectInternal cls, string reason, int priority) { - strictcount(cls.(PythonClassObjectInternal).getScope().getADecorator()) > 1 and reason = "Multiple decorators" and priority = 0 + strictcount(cls.(PythonClassObjectInternal).getScope().getADecorator()) > 1 and + reason = "Multiple decorators" and + priority = 0 or - exists(cls.(PythonClassObjectInternal).getScope().getADecorator()) and not six_add_metaclass(_, _, cls, _) and reason = "Decorator not understood" and priority = 1 + exists(cls.(PythonClassObjectInternal).getScope().getADecorator()) and + not six_add_metaclass(_, _, cls, _) and + reason = "Decorator not understood" and + priority = 1 or reason = "Missing base " + missingBase(cls) and priority = 6 or - not exists(ObjectInternal meta | meta = cls.getClass() and not meta = ObjectInternal::unknownClass()) and reason = "Failed to infer metaclass" and priority = 4 + not exists(ObjectInternal meta | + meta = cls.getClass() and not meta = ObjectInternal::unknownClass() + ) and + reason = "Failed to infer metaclass" and + priority = 4 or exists(int i, ObjectInternal base1, ObjectInternal base2 | base1 = getBase(cls, i) and base2 = getBase(cls, i) and base1 != base2 and reason = "Multiple bases at position " + i - ) and priority = 6 + ) and + priority = 6 or duplicateBase(cls) and reason = "Duplicate bases classes" and priority = 6 or not exists(getMro(cls)) and reason = "Failed to compute MRO" and priority = 3 or - exists(int i | failedInference(getBase(cls, i), _, _) and reason = "Failed inference for base class at position " + i) and priority = 5 + exists(int i | + failedInference(getBase(cls, i), _, _) and + reason = "Failed inference for base class at position " + i + ) and + priority = 5 } private int missingBase(ClassObjectInternal cls) { exists(cls.(PythonClassObjectInternal).getScope().getBase(result)) and - not exists(ObjectInternal base | base = getBase(cls, result) and not base = ObjectInternal::unknownClass()) - } - - private predicate duplicateBase(ClassObjectInternal cls) { - exists(int i, int j, ClassObjectInternal dup | - dup = getBase(cls, i) and dup != ObjectInternal::unknownClass() and - dup = getBase(cls, j) and i != j + not exists(ObjectInternal base | + base = getBase(cls, result) and not base = ObjectInternal::unknownClass() ) } - cached boolean improperSubclass(ObjectInternal sub, ObjectInternal sup) { + private predicate duplicateBase(ClassObjectInternal cls) { + exists(int i, int j, ClassObjectInternal dup | + dup = getBase(cls, i) and + dup != ObjectInternal::unknownClass() and + dup = getBase(cls, j) and + i != j + ) + } + + cached + boolean improperSubclass(ObjectInternal sub, ObjectInternal sup) { sub = sup and result = true or result = true and mroContains(Types::getMro(sub), sup) @@ -2093,7 +2396,7 @@ cached module Types { ( n = tpl.length() and result = false or - result = improperSubclass(cls, tpl.getItem(n)).booleanOr(tupleSubclass(cls, tpl, n+1)) + result = improperSubclass(cls, tpl.getItem(n)).booleanOr(tupleSubclass(cls, tpl, n + 1)) ) } @@ -2111,12 +2414,11 @@ cached module Types { exists(ClassObjectInternal cls | Expressions::requireSubClass(cls, sup) and mro = getMro(cls) - ) - and + ) and ( n = mro.length() or - mroDoesnotContain(mro, sup, n+1) and + mroDoesnotContain(mro, sup, n + 1) and mro.getItem(n) != sup and exists(ClassDecl item, ClassDecl sdecl | item = mro.getItem(n).getClassDeclaration() and @@ -2140,7 +2442,8 @@ cached module Types { cls = Builtin::builtin("dict") and sup.isAbstractBaseClass("Iterable") } - cached boolean hasAttr(ObjectInternal cls, string name) { + cached + boolean hasAttr(ObjectInternal cls, string name) { result = mroHasAttr(Types::getMro(cls), name, 0) } @@ -2148,28 +2451,24 @@ cached module Types { exists(ClassObjectInternal cls | Expressions::requireHasAttr(cls, name) and mro = getMro(cls) - ) - and + ) and ( n = mro.length() and result = false or - exists(ClassDecl decl | - decl = mro.getItem(n).getClassDeclaration() | - if decl.declaresAttribute(name) then - result = true - else - result = mroHasAttr(mro, name, n+1) + exists(ClassDecl decl | decl = mro.getItem(n).getClassDeclaration() | + if decl.declaresAttribute(name) + then result = true + else result = mroHasAttr(mro, name, n + 1) ) ) } - } - module AttributePointsTo { - - pragma [noinline] - predicate pointsTo(ControlFlowNode f, Context context, ObjectInternal value, ControlFlowNode origin) { + pragma[noinline] + predicate pointsTo( + ControlFlowNode f, Context context, ObjectInternal value, ControlFlowNode origin + ) { exists(EssaVariable var, string name, CfgOrigin orig | getsVariableAttribute(f, var, name) and variableAttributePointsTo(var, context, name, value, orig) and @@ -2177,15 +2476,17 @@ module AttributePointsTo { ) } - pragma [noinline] + pragma[noinline] private predicate getsVariableAttribute(ControlFlowNode f, EssaVariable var, string name) { Expressions::getattr_call(f, var.getASourceUse(), _, _, name) or f.isLoad() and var.getASourceUse() = f.(AttrNode).getObject(name) } - pragma [nomagic] - predicate variableAttributePointsTo(EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + predicate variableAttributePointsTo( + EssaVariable var, Context context, string name, ObjectInternal value, CfgOrigin origin + ) { definitionAttributePointsTo(var.getDefinition(), context, name, value, origin) or exists(EssaVariable prev | @@ -2194,7 +2495,9 @@ module AttributePointsTo { ) } - predicate definitionAttributePointsTo(EssaDefinition def, Context context, string name, ObjectInternal value, CfgOrigin origin) { + predicate definitionAttributePointsTo( + EssaDefinition def, Context context, string name, ObjectInternal value, CfgOrigin origin + ) { variableAttributePointsTo(def.(PhiFunction).getAnInput(), context, name, value, origin) or piNodeAttributePointsTo(def, context, name, value, origin) @@ -2208,8 +2511,11 @@ module AttributePointsTo { argumentRefinementPointsTo(def, context, name, value, origin) } - pragma [noinline] - private predicate refinementAttributePointsTo(EssaNodeRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate refinementAttributePointsTo( + EssaNodeRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { attributeAssignmentAttributePointsTo(def, context, name, value, origin) or attributeDeleteAttributePointsTo(def, context, name, value, origin) @@ -2217,10 +2523,12 @@ module AttributePointsTo { uniEdgedPhiAttributePointsTo(def, context, name, value, origin) } - /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attributeAssignmentAttributePointsTo(AttributeAssignment def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attributeAssignmentAttributePointsTo( + AttributeAssignment def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { def.getName() != name and variableAttributePointsTo(def.getInput(), context, name, value, origin) or @@ -2232,41 +2540,60 @@ module AttributePointsTo { } /** Attribute deletions have no effect as far as value tracking is concerned. */ - pragma [noinline] - private predicate attributeDeleteAttributePointsTo(EssaAttributeDeletion def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate attributeDeleteAttributePointsTo( + EssaAttributeDeletion def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { def.getName() != name and variableAttributePointsTo(def.getInput(), context, name, value, origin) } - private predicate uniEdgedPhiAttributePointsTo(SingleSuccessorGuard unipi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate uniEdgedPhiAttributePointsTo( + SingleSuccessorGuard unipi, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { variableAttributePointsTo(unipi.getInput(), context, name, value, origin) } - private predicate piNodeAttributePointsTo(PyEdgeRefinement pi, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate piNodeAttributePointsTo( + PyEdgeRefinement pi, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { variableAttributePointsTo(pi.getInput(), context, name, value, origin) } - private predicate selfParameterAttributePointsTo(ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate selfParameterAttributePointsTo( + ParameterDefinition def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { exists(SelfCallsiteRefinement call, Function func, PointsToContext caller | InterProceduralPointsTo::selfMethodCall(call, caller, func, context) and - def.isSelf() and def.getScope() = func and + def.isSelf() and + def.getScope() = func and variableAttributePointsTo(call.getInput(), caller, name, value, origin) ) } /** Pass through for `self` for the implicit re-definition of `self` in `self.foo()`. */ - private predicate selfMethodCallsitePointsTo(SelfCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate selfMethodCallsitePointsTo( + SelfCallsiteRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { /* The value of self remains the same, only the attributes may change */ exists(Function func, PointsToContext callee, EssaVariable exit_self | InterProceduralPointsTo::selfMethodCall(def, context, func, callee) and exit_self.getSourceVariable().(Variable).isSelf() and - exit_self.getScope() = func and + exit_self.getScope() = func and BaseFlow::reaches_exit(exit_self) and variableAttributePointsTo(exit_self, callee, name, value, origin) ) } - private predicate argumentRefinementPointsTo(ArgumentRefinement def, PointsToContext context, string name, ObjectInternal value, CfgOrigin origin) { + private predicate argumentRefinementPointsTo( + ArgumentRefinement def, PointsToContext context, string name, ObjectInternal value, + CfgOrigin origin + ) { exists(ObjectInternal callable | PointsToInternal::pointsTo(def.getCall().getFunction(), context, callable, _) and callable != ObjectInternal::builtin("setattr") @@ -2274,21 +2601,22 @@ module AttributePointsTo { variableAttributePointsTo(def.getInput(), context, name, value, origin) or exists(string othername | - Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), othername, _, _) and + Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), othername, + _, _) and not othername = name ) and variableAttributePointsTo(def.getInput(), context, name, value, origin) or exists(ControlFlowNode orig | - Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), name, value, orig) and + Expressions::setattr_call(def.getCall(), context, def.getInput().getASourceUse(), name, value, + orig) and origin = CfgOrigin::fromCfgNode(orig) ) } - } -cached module ModuleAttributes { - +cached +module ModuleAttributes { private EssaVariable varAtExit(Module mod, string name) { result.getName() = name and result.getAUse() = mod.getANormalExit() } @@ -2301,15 +2629,17 @@ cached module ModuleAttributes { result = moduleStateVariable(mod.getANormalExit()) } - cached predicate pointsToAtExit(Module mod, string name, ObjectInternal value, CfgOrigin origin) { - if exists(varAtExit(mod, name)) then ( - PointsToInternal::variablePointsTo(varAtExit(mod, name), any(Context c | c.isImport()), value, origin) - ) else ( - attributePointsTo(moduleStateVarAtExit(mod), name, value, origin) - ) + cached + predicate pointsToAtExit(Module mod, string name, ObjectInternal value, CfgOrigin origin) { + if exists(varAtExit(mod, name)) + then + PointsToInternal::variablePointsTo(varAtExit(mod, name), any(Context c | c.isImport()), value, + origin) + else attributePointsTo(moduleStateVarAtExit(mod), name, value, origin) } - cached predicate attributePointsTo(EssaVariable var, string name, ObjectInternal value, CfgOrigin origin) { + cached + predicate attributePointsTo(EssaVariable var, string name, ObjectInternal value, CfgOrigin origin) { importStarPointsTo(var.getDefinition(), name, value, origin) or callsitePointsTo(var.getDefinition(), name, value, origin) @@ -2320,7 +2650,7 @@ cached module ModuleAttributes { } /** Holds if the phi-function `phi` refers to `(value, origin)` given the context `context`. */ - pragma [nomagic] + pragma[nomagic] private predicate phiPointsTo(PhiFunction phi, string name, ObjectInternal value, CfgOrigin origin) { exists(EssaVariable input | PointsToInternal::ssa_phi_reachable_from_input(phi, any(Context c | c.isImport()), input) and @@ -2328,17 +2658,19 @@ cached module ModuleAttributes { ) } - pragma [nomagic] - private predicate importStarPointsTo(ImportStarRefinement def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[nomagic] + private predicate importStarPointsTo( + ImportStarRefinement def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and /* Attribute from imported module */ exists(ModuleObjectInternal mod | - importStarDef(def, _, mod) - and + importStarDef(def, _, mod) and /* Attribute from imported module */ exists(CfgOrigin orig | InterModulePointsTo::moduleExportsBoolean(mod, name) = true and - mod.attribute(name, value, orig) and origin = orig.fix(def.getDefiningNode()) and + mod.attribute(name, value, orig) and + origin = orig.fix(def.getDefiningNode()) and not exists(Variable v | v.getId() = name and v.getScope() = def.getScope()) ) ) @@ -2351,19 +2683,26 @@ cached module ModuleAttributes { ) } - private predicate importStarDef(ImportStarRefinement def, EssaVariable input, ModuleObjectInternal mod) { + private predicate importStarDef( + ImportStarRefinement def, EssaVariable input, ModuleObjectInternal mod + ) { exists(ImportStarNode imp | - def.getVariable().getName() = "$" and imp = def.getDefiningNode() and - input = def.getInput() and PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) + def.getVariable().getName() = "$" and + imp = def.getDefiningNode() and + input = def.getInput() and + PointsToInternal::importCtxPointsTo(imp.getModule(), mod, _) ) } - /** Points-to for a variable (possibly) redefined by a call: + /** + * Points-to for a variable (possibly) redefined by a call: * `var = ...; foo(); use(var)` * Where var may be redefined in call to `foo` if `var` escapes (is global or non-local). */ - pragma [noinline] - private predicate callsitePointsTo(CallsiteRefinement def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate callsitePointsTo( + CallsiteRefinement def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and exists(EssaVariable var, Function func, PointsToContext callee | InterProceduralPointsTo::callsite_calls_function(def.getCall(), _, func, callee, _) and @@ -2372,18 +2711,21 @@ cached module ModuleAttributes { ) } - /** Holds if the attribute name of the implicit '$' variable refers to `value` at the start of the scope. + /** + * Holds if the attribute name of the implicit '$' variable refers to `value` at the start of the scope. * Since it cannot refer to any actual value, it is set to "undefined" for sub module names. */ - pragma [noinline] - private predicate scopeEntryPointsTo(ScopeEntryDefinition def, string name, ObjectInternal value, CfgOrigin origin) { + pragma[noinline] + private predicate scopeEntryPointsTo( + ScopeEntryDefinition def, string name, ObjectInternal value, CfgOrigin origin + ) { def.getVariable().isMetaVariable() and exists(Module m | def.getScope() = m and not exists(EssaVariable named | named.getName() = name and named.getScope() = m) and value = ObjectInternal::undefined() and origin = CfgOrigin::unknown() - | + | m.isPackageInit() and exists(m.getPackage().getSubModule(name)) or not m.declaredInAll(_) and @@ -2393,6 +2735,4 @@ cached module ModuleAttributes { ) ) } - } - diff --git a/python/ql/src/semmle/python/pointsto/PointsToContext.qll b/python/ql/src/semmle/python/pointsto/PointsToContext.qll index 8804a51f9cb..a82a62130b2 100644 --- a/python/ql/src/semmle/python/pointsto/PointsToContext.qll +++ b/python/ql/src/semmle/python/pointsto/PointsToContext.qll @@ -1,6 +1,7 @@ import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal + /* * A note on 'cost'. Cost doesn't represent the cost to compute, * but (a vague estimate of) the cost to compute per value gained. @@ -14,7 +15,7 @@ private int given_cost() { ) } -pragma [noinline] +pragma[noinline] private int max_context_cost() { not py_flags_versioned("context.cost", _, _) and result = 7 or @@ -22,13 +23,13 @@ private int max_context_cost() { } private int syntactic_call_count(Scope s) { - exists(Function f | - f = s and f.getName() != "__init__" | - result = count(CallNode call | - call.getFunction().(NameNode).getId() = f.getName() - or - call.getFunction().(AttrNode).getName() = f.getName() - ) + exists(Function f | f = s and f.getName() != "__init__" | + result = + count(CallNode call | + call.getFunction().(NameNode).getId() = f.getName() + or + call.getFunction().(AttrNode).getName() = f.getName() + ) ) or s.getName() = "__init__" and result = 1 @@ -37,11 +38,13 @@ private int syntactic_call_count(Scope s) { } private int incoming_call_cost(Scope s) { - /* Syntactic call count will often be a considerable overestimate + /* + * Syntactic call count will often be a considerable overestimate * of the actual number of calls, so we use the square root. * Cost = log(sqrt(call-count)) */ - result = ((syntactic_call_count(s)+1).log(2)*0.5).floor() + + result = ((syntactic_call_count(s) + 1).log(2) * 0.5).floor() } private int context_cost(TPointsToContext ctx) { @@ -55,15 +58,10 @@ private int context_cost(TPointsToContext ctx) { } private int call_cost(CallNode call) { - if call.getScope().inSource() then - result = 2 - else - result = 3 + if call.getScope().inSource() then result = 2 else result = 3 } -private int outgoing_calls(Scope s) { - result = strictcount(CallNode call | call.getScope() = s) -} +private int outgoing_calls(Scope s) { result = strictcount(CallNode call | call.getScope() = s) } predicate super_method_call(CallNode call) { call.getFunction().(AttrNode).getObject().(CallNode).getFunction().(NameNode).getId() = "super" @@ -74,74 +72,65 @@ private int outgoing_call_cost(CallNode c) { result = outgoing_calls(c.getScope()).log(2).floor() } -/** Cost of contexts for a call, the more callers the +/** + * Cost of contexts for a call, the more callers the * callee of call has the more expensive it is to add contexts for it. * This seems to be an effective heuristics for preventing an explosion * in the number of contexts while retaining good results. */ private int splay_cost(CallNode c) { - if super_method_call(c) then - result = 0 - else - result = outgoing_call_cost(c) + incoming_call_cost(c.getScope()) + if super_method_call(c) + then result = 0 + else result = outgoing_call_cost(c) + incoming_call_cost(c.getScope()) } private predicate call_to_init_or_del(CallNode call) { - exists(string mname | - mname = "__init__" or mname = "__del__" | + exists(string mname | mname = "__init__" or mname = "__del__" | mname = call.getFunction().(AttrNode).getName() ) } /** Total cost estimate */ private int total_call_cost(CallNode call) { - /* We want to always follow __init__ and __del__ calls as they tell us about object construction, + /* + * We want to always follow __init__ and __del__ calls as they tell us about object construction, * but we need to be aware of cycles, so they must have a non-zero cost. */ - if call_to_init_or_del(call) then - result = 1 - else - result = call_cost(call) + splay_cost(call) + + if call_to_init_or_del(call) then result = 1 else result = call_cost(call) + splay_cost(call) } -pragma [noinline] +pragma[noinline] private int total_cost(CallNode call, PointsToContext ctx) { ctx.appliesTo(call) and result = total_call_cost(call) + context_cost(ctx) } -private cached newtype TPointsToContext = - TMainContext() - or - TRuntimeContext() - or - TImportContext() - or +cached +private newtype TPointsToContext = + TMainContext() or + TRuntimeContext() or + TImportContext() or TCallContext(ControlFlowNode call, PointsToContext outerContext, int cost) { total_cost(call, outerContext) = cost and cost <= max_context_cost() - } - or + } or TObjectContext(SelfInstanceInternal object) module Context { - - PointsToContext forObject(ObjectInternal object) { - result = TObjectContext(object) - } - + PointsToContext forObject(ObjectInternal object) { result = TObjectContext(object) } } - -/** Points-to context. Context can be one of: +/** + * Points-to context. Context can be one of: * * "main": Used for scripts. * * "import": Use for non-script modules. * * "default": Use for functions and methods without caller context. * * All other contexts are call contexts and consist of a pair of call-site and caller context. */ class PointsToContext extends TPointsToContext { - - cached string toString() { + cached + string toString() { this = TMainContext() and result = "main" or this = TRuntimeContext() and result = "runtime" @@ -166,10 +155,8 @@ class PointsToContext extends TPointsToContext { this = TCallContext(call, caller, _) } - /** Gets the caller context for this callee context. */ - PointsToContext getOuter() { - this = TCallContext(_, result, _) - } + /** Gets the caller context for this callee context. */ + PointsToContext getOuter() { this = TCallContext(_, result, _) } /** Holds if this context is relevant to the given scope. */ predicate appliesToScope(Scope s) { @@ -182,9 +169,12 @@ class PointsToContext extends TPointsToContext { this = TRuntimeContext() and executes_in_runtime_context(s) or /* Called functions, regardless of their name */ - exists(PythonFunctionObjectInternal callable, ControlFlowNode call, TPointsToContext outerContext | + exists( + PythonFunctionObjectInternal callable, ControlFlowNode call, TPointsToContext outerContext + | call = callable.getACall(outerContext) and - this = TCallContext(call, outerContext, _) | + this = TCallContext(call, outerContext, _) + | s = callable.getScope() ) or @@ -192,30 +182,20 @@ class PointsToContext extends TPointsToContext { } /** Holds if this context can apply to the CFG node `n`. */ - pragma [inline] - predicate appliesTo(ControlFlowNode n) { - this.appliesToScope(n.getScope()) - } + pragma[inline] + predicate appliesTo(ControlFlowNode n) { this.appliesToScope(n.getScope()) } /** Holds if this context is a call context. */ - predicate isCall() { - this = TCallContext(_, _, _) - } + predicate isCall() { this = TCallContext(_, _, _) } /** Holds if this is the "main" context. */ - predicate isMain() { - this = TMainContext() - } + predicate isMain() { this = TMainContext() } /** Holds if this is the "import" context. */ - predicate isImport() { - this = TImportContext() - } + predicate isImport() { this = TImportContext() } /** Holds if this is the "default" context. */ - predicate isRuntime() { - this = TRuntimeContext() - } + predicate isRuntime() { this = TRuntimeContext() } /** Holds if this context or one of its caller contexts is the default context. */ predicate fromRuntime() { @@ -231,19 +211,13 @@ class PointsToContext extends TPointsToContext { result = this.getOuter().getDepth() + 1 } - int getCost() { - result = context_cost(this) - } + int getCost() { result = context_cost(this) } - CallNode getCall() { - this = TCallContext(result, _, _) - } + CallNode getCall() { this = TCallContext(result, _, _) } /** Holds if a call would be too expensive to create a new context for */ - pragma [nomagic] - predicate untrackableCall(CallNode call) { - total_cost(call, this) > max_context_cost() - } + pragma[nomagic] + predicate untrackableCall(CallNode call) { total_cost(call, this) > max_context_cost() } CallNode getRootCall() { this = TCallContext(result, TImportContext(), _) @@ -252,35 +226,30 @@ class PointsToContext extends TPointsToContext { } /** Gets a version of Python that this context includes */ - pragma [inline] + pragma[inline] Version getAVersion() { /* Currently contexts do not include any version information, but may do in the future */ result = major_version() } - } -private predicate in_source(Scope s) { - exists(s.getEnclosingModule().getFile().getRelativePath()) -} +private predicate in_source(Scope s) { exists(s.getEnclosingModule().getFile().getRelativePath()) } -/** Holds if this scope can be executed in the default context. +/** + * Holds if this scope can be executed in the default context. * All modules and classes executed at import time and * all "public" functions and methods, including those invoked by the VM. */ predicate executes_in_runtime_context(Function f) { /* "Public" scope, i.e. functions whose name starts not with an underscore, or special methods */ - (f.getName().charAt(0) != "_" or f.isSpecialMethod() or f.isInitMethod()) - and + (f.getName().charAt(0) != "_" or f.isSpecialMethod() or f.isInitMethod()) and in_source(f) } private predicate maybe_main(Module m) { - exists(If i, Compare cmp, Name name, StrConst main | - m.getAStmt() = i and i.getTest() = cmp | + exists(If i, Compare cmp, Name name, StrConst main | m.getAStmt() = i and i.getTest() = cmp | cmp.compares(name, any(Eq eq), main) and name.getId() = "__name__" and main.getText() = "__main__" ) } - diff --git a/python/ql/src/semmle/python/protocols.qll b/python/ql/src/semmle/python/protocols.qll index 31808ff3c53..f1f7e6a3ed7 100644 --- a/python/ql/src/semmle/python/protocols.qll +++ b/python/ql/src/semmle/python/protocols.qll @@ -1,31 +1,19 @@ import python /** Retained for backwards compatibility use ClassObject.isIterator() instead. */ -predicate is_iterator(ClassObject c) { - c.isIterator() -} +predicate is_iterator(ClassObject c) { c.isIterator() } /** Retained for backwards compatibility use ClassObject.isIterable() instead. */ -predicate is_iterable(ClassObject c) { - c.isIterable() -} +predicate is_iterable(ClassObject c) { c.isIterable() } /** Retained for backwards compatibility use ClassObject.isCollection() instead. */ -predicate is_collection(ClassObject c) { - c.isCollection() -} +predicate is_collection(ClassObject c) { c.isCollection() } /** Retained for backwards compatibility use ClassObject.isMapping() instead. */ -predicate is_mapping(ClassObject c) { - c.isMapping() -} +predicate is_mapping(ClassObject c) { c.isMapping() } /** Retained for backwards compatibility use ClassObject.isSequence() instead. */ -predicate is_sequence(ClassObject c) { - c.isSequence() -} +predicate is_sequence(ClassObject c) { c.isSequence() } /** Retained for backwards compatibility use ClassObject.isContextManager() instead. */ -predicate is_context_manager(ClassObject c) { - c.isContextManager() -} +predicate is_context_manager(ClassObject c) { c.isContextManager() } diff --git a/python/ql/src/semmle/python/regex.qll b/python/ql/src/semmle/python/regex.qll index 2e83d8fca35..bd7469ea830 100644 --- a/python/ql/src/semmle/python/regex.qll +++ b/python/ql/src/semmle/python/regex.qll @@ -2,13 +2,20 @@ import python import semmle.python.objects.ObjectInternal private predicate re_module_function(string name, int flags) { - name = "compile" and flags = 1 or - name = "search" and flags = 2 or - name = "match" and flags = 2 or - name = "split" and flags = 3 or - name = "findall" and flags = 2 or - name = "finditer" and flags = 2 or - name = "sub" and flags = 4 or + name = "compile" and flags = 1 + or + name = "search" and flags = 2 + or + name = "match" and flags = 2 + or + name = "split" and flags = 3 + or + name = "findall" and flags = 2 + or + name = "finditer" and flags = 2 + or + name = "sub" and flags = 4 + or name = "subn" and flags = 4 } @@ -17,16 +24,15 @@ private predicate re_module_function(string name, int flags) { * If regex mode is not known, `mode` will be `"None"`. */ predicate used_as_regex(Expr s, string mode) { - (s instanceof Bytes or s instanceof Unicode) - and + (s instanceof Bytes or s instanceof Unicode) and /* Call to re.xxx(regex, ... [mode]) */ exists(CallNode call, string name | call.getArg(0).refersTo(_, _, s.getAFlowNode()) and - call.getFunction().pointsTo(Module::named("re").attr(name)) | + call.getFunction().pointsTo(Module::named("re").attr(name)) + | mode = "None" or - exists(Value obj | - mode = mode_from_mode_object(obj) | + exists(Value obj | mode = mode_from_mode_object(obj) | exists(int flags_arg | re_module_function(name, flags_arg) and call.getArg(flags_arg).pointsTo(obj) @@ -39,30 +45,30 @@ predicate used_as_regex(Expr s, string mode) { string mode_from_mode_object(Value obj) { ( - result = "DEBUG" or result = "IGNORECASE" or result = "LOCALE" or - result = "MULTILINE" or result = "DOTALL" or result = "UNICODE" or + result = "DEBUG" or + result = "IGNORECASE" or + result = "LOCALE" or + result = "MULTILINE" or + result = "DOTALL" or + result = "UNICODE" or result = "VERBOSE" ) and exists(int flag | - flag = Value::named("sre_constants.SRE_FLAG_" + result).(ObjectInternal).intValue() - and + flag = Value::named("sre_constants.SRE_FLAG_" + result).(ObjectInternal).intValue() and obj.(ObjectInternal).intValue().bitAnd(flag) = flag ) } /** A StrConst used as a regular expression */ abstract class RegexString extends Expr { - - RegexString() { - (this instanceof Bytes or this instanceof Unicode) - } + RegexString() { (this instanceof Bytes or this instanceof Unicode) } predicate char_set_start(int start, int end) { this.nonEscapedCharAt(start) = "[" and ( - this.getChar(start+1) = "^" and end = start + 2 - or - not this.getChar(start+1) = "^" and end = start + 1 + this.getChar(start + 1) = "^" and end = start + 2 + or + not this.getChar(start + 1) = "^" and end = start + 1 ) } @@ -70,58 +76,47 @@ abstract class RegexString extends Expr { predicate charSet(int start, int end) { exists(int inner_start, int inner_end | this.char_set_start(start, inner_start) and - not this.char_set_start(_, start) | - end = inner_end + 1 and inner_end > inner_start and + not this.char_set_start(_, start) + | + end = inner_end + 1 and + inner_end > inner_start and this.nonEscapedCharAt(inner_end) = "]" and - not exists(int mid | this.nonEscapedCharAt(mid) = "]" | - mid > inner_start and mid < inner_end - ) + not exists(int mid | this.nonEscapedCharAt(mid) = "]" | mid > inner_start and mid < inner_end) ) } - predicate escapingChar(int pos) { - this.escaping(pos) = true - } + predicate escapingChar(int pos) { this.escaping(pos) = true } private boolean escaping(int pos) { pos = -1 and result = false or - this.getChar(pos) = "\\" and result = this.escaping(pos-1).booleanNot() + this.getChar(pos) = "\\" and result = this.escaping(pos - 1).booleanNot() or this.getChar(pos) != "\\" and result = false } /** Gets the text of this regex */ string getText() { - result = ((Unicode)this).getS() + result = this.(Unicode).getS() or - result = ((Bytes)this).getS() + result = this.(Bytes).getS() } - string getChar(int i) { - result = this.getText().charAt(i) - } + string getChar(int i) { result = this.getText().charAt(i) } string nonEscapedCharAt(int i) { result = this.getText().charAt(i) and - not this.escapingChar(i-1) + not this.escapingChar(i - 1) } - private predicate isOptionDivider(int i) { - this.nonEscapedCharAt(i) = "|" - } + private predicate isOptionDivider(int i) { this.nonEscapedCharAt(i) = "|" } - private predicate isGroupEnd(int i) { - this.nonEscapedCharAt(i) = ")" - } + private predicate isGroupEnd(int i) { this.nonEscapedCharAt(i) = ")" } - private predicate isGroupStart(int i) { - this.nonEscapedCharAt(i) = "(" - } + private predicate isGroupStart(int i) { this.nonEscapedCharAt(i) = "(" } predicate failedToParse(int i) { - exists(this.getChar(i)) - and + exists(this.getChar(i)) and not exists(int start, int end | this.top_level(start, end) and start <= i and @@ -130,42 +125,47 @@ abstract class RegexString extends Expr { } private predicate escapedCharacter(int start, int end) { - this.escapingChar(start) and not exists(this.getText().substring(start+1, end+1).toInt()) and + this.escapingChar(start) and + not exists(this.getText().substring(start + 1, end + 1).toInt()) and ( - this.getChar(start+1) = "x" and end = start + 4 + this.getChar(start + 1) = "x" and end = start + 4 or - end in [start+2..start+4] and - exists(this.getText().substring(start+1, end).toInt()) + end in [start + 2 .. start + 4] and + exists(this.getText().substring(start + 1, end).toInt()) or - this.getChar(start+1) != "x" and end = start + 2 + this.getChar(start + 1) != "x" and end = start + 2 ) } private predicate inCharSet(int index) { - exists(int x, int y | this.charSet(x, y) and index in [x+1 .. y-2]) + exists(int x, int y | this.charSet(x, y) and index in [x + 1 .. y - 2]) } - /* 'simple' characters are any that don't alter the parsing of the regex. + /* + * 'simple' characters are any that don't alter the parsing of the regex. */ + private predicate simpleCharacter(int start, int end) { - end = start+1 and + end = start + 1 and not this.charSet(start, _) and - not this.charSet(_, start+1) and - exists(string c | - c = this.getChar(start) | + not this.charSet(_, start + 1) and + exists(string c | c = this.getChar(start) | exists(int x, int y, int z | - this.charSet(x, z) and - this.char_set_start(x, y) | + this.charSet(x, z) and + this.char_set_start(x, y) + | start = y or - start = z-2 + start = z - 2 or - start > y and start < z-2 and not c = "-" + start > y and start < z - 2 and not c = "-" ) or not this.inCharSet(start) and - not c = "(" and not c = "[" and - not c = ")" and not c = "|" and + not c = "(" and + not c = "[" and + not c = ")" and + not c = "|" and not this.qualifier(start, _, _) ) } @@ -176,28 +176,20 @@ abstract class RegexString extends Expr { not exists(int x, int y | this.escapedCharacter(x, y) and x <= start and y >= end) or this.escapedCharacter(start, end) - ) - and - not exists(int x, int y | - this.group_start(x, y) and x <= start and y >= end - ) + ) and + not exists(int x, int y | this.group_start(x, y) and x <= start and y >= end) } predicate normalCharacter(int start, int end) { - this.character(start, end) - and + this.character(start, end) and not this.specialCharacter(start, end, _) } predicate specialCharacter(int start, int end, string char) { - this.character(start, end) - and - end = start+1 - and - char = this.getChar(start) - and - (char = "$" or char = "^" or char = ".") - and + this.character(start, end) and + end = start + 1 and + char = this.getChar(start) and + (char = "$" or char = "^" or char = ".") and not this.inCharSet(start) } @@ -210,17 +202,17 @@ abstract class RegexString extends Expr { /** Gets the number of the group in start,end */ int getGroupNumber(int start, int end) { - this.group(start, end) and - result = count(int i | this.group(i, _) and i < start and not this.non_capturing_group_start(i, _)) + 1 + this.group(start, end) and + result = + count(int i | this.group(i, _) and i < start and not this.non_capturing_group_start(i, _)) + 1 } /** Gets the name, if it has one, of the group in start,end */ string getGroupName(int start, int end) { - this.group(start, end) - and + this.group(start, end) and exists(int name_end | this.named_group_start(start, name_end) and - result = this.getText().substring(start+4, name_end-1) + result = this.getText().substring(start + 4, name_end - 1) ) } @@ -236,8 +228,7 @@ abstract class RegexString extends Expr { } private predicate emptyGroup(int start, int end) { - exists(int endm1 | - end = endm1+1 | + exists(int endm1 | end = endm1 + 1 | this.group_start(start, endm1) and this.isGroupEnd(endm1) ) @@ -263,21 +254,20 @@ abstract class RegexString extends Expr { exists(int in_start | this.negative_lookahead_assertion_start(start, in_start) or - this.negative_lookbehind_assertion_start(start, in_start) | + this.negative_lookbehind_assertion_start(start, in_start) + | this.groupContents(start, end, in_start, _) ) } private predicate positiveLookaheadAssertionGroup(int start, int end) { - exists(int in_start | - this.lookahead_assertion_start(start, in_start) | + exists(int in_start | this.lookahead_assertion_start(start, in_start) | this.groupContents(start, end, in_start, _) ) } private predicate positiveLookbehindAssertionGroup(int start, int end) { - exists(int in_start | - this.lookbehind_assertion_start(start, in_start) | + exists(int in_start | this.lookbehind_assertion_start(start, in_start) | this.groupContents(start, end, in_start, _) ) } @@ -306,42 +296,43 @@ abstract class RegexString extends Expr { private predicate non_capturing_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = ":" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = ":" and + end = start + 3 } private predicate simple_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) != "?" and end = start+1 + this.getChar(start + 1) != "?" and + end = start + 1 } private predicate named_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "P" and - this.getChar(start+3) = "<" and - not this.getChar(start+4) = "=" and - not this.getChar(start+4) = "!" and + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "P" and + this.getChar(start + 3) = "<" and + not this.getChar(start + 4) = "=" and + not this.getChar(start + 4) = "!" and exists(int name_end | - name_end = min(int i | i > start+4 and this.getChar(i) = ">") and + name_end = min(int i | i > start + 4 and this.getChar(i) = ">") and end = name_end + 1 ) } private predicate named_backreference_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "P" and - this.getChar(start+3) = "=" and - end = min(int i | i > start+4 and this.getChar(i) = "?") + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "P" and + this.getChar(start + 3) = "=" and + end = min(int i | i > start + 4 and this.getChar(i) = "?") } private predicate flag_group_start(int start, int end, string c) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - end = start+3 and - c = this.getChar(start+2) and + this.getChar(start + 1) = "?" and + end = start + 3 and + c = this.getChar(start + 2) and ( c = "i" or c = "L" or @@ -352,12 +343,12 @@ abstract class RegexString extends Expr { ) } - /** Gets the mode of this regular expression string if + /** + * Gets the mode of this regular expression string if * it is defined by a prefix. */ string getModeFromPrefix() { - exists(string c | - this.flag_group_start(_, _, c) | + exists(string c | this.flag_group_start(_, _, c) | c = "i" and result = "IGNORECASE" or c = "L" and result = "LOCALE" @@ -366,7 +357,7 @@ abstract class RegexString extends Expr { or c = "s" and result = "DOTALL" or - c = "u" and result = "UNICODE" + c = "u" and result = "UNICODE" or c = "x" and result = "VERBOSE" ) @@ -374,39 +365,39 @@ abstract class RegexString extends Expr { private predicate lookahead_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "=" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "=" and + end = start + 3 } private predicate negative_lookahead_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "!" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "!" and + end = start + 3 } private predicate lookbehind_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "<" and - this.getChar(start+3) = "=" and - end = start+4 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "<" and + this.getChar(start + 3) = "=" and + end = start + 4 } private predicate negative_lookbehind_assertion_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "<" and - this.getChar(start+3) = "!" and - end = start+4 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "<" and + this.getChar(start + 3) = "!" and + end = start + 4 } private predicate comment_group_start(int start, int end) { this.isGroupStart(start) and - this.getChar(start+1) = "?" and - this.getChar(start+2) = "#" and - end = start+3 + this.getChar(start + 1) = "?" and + this.getChar(start + 2) = "#" and + end = start + 3 } predicate groupContents(int start, int end, int in_start, int in_end) { @@ -417,20 +408,21 @@ abstract class RegexString extends Expr { } private predicate named_backreference(int start, int end, string name) { - this.named_backreference_start(start, start+4) and - end = min(int i | i > start+4 and this.getChar(i) = ")") + 1 and - name = this.getText().substring(start+4, end-2) + this.named_backreference_start(start, start + 4) and + end = min(int i | i > start + 4 and this.getChar(i) = ")") + 1 and + name = this.getText().substring(start + 4, end - 2) } private predicate numbered_backreference(int start, int end, int value) { - this.escapingChar(start) - and + this.escapingChar(start) and exists(string text, string svalue, int len | end = start + len and - text = this.getText() and len in [2..3] | - svalue = text.substring(start+1, start+len) and + text = this.getText() and + len in [2 .. 3] + | + svalue = text.substring(start + 1, start + len) and value = svalue.toInt() and - not exists(text.substring(start+1, start+len+1).toInt()) and + not exists(text.substring(start + 1, start + len + 1).toInt()) and value != 0 ) } @@ -443,17 +435,14 @@ abstract class RegexString extends Expr { } /** Gets the number of the back reference in start,end */ - int getBackrefNumber(int start, int end) { - this.numbered_backreference(start, end, result) - } + int getBackrefNumber(int start, int end) { this.numbered_backreference(start, end, result) } /** Gets the name, if it has one, of the back reference in start,end */ - string getBackrefName(int start, int end) { - this.named_backreference(start, end, result) - } + string getBackrefName(int start, int end) { this.named_backreference(start, end, result) } private predicate baseItem(int start, int end) { - this.character(start, end) and not exists(int x, int y | this.charSet(x, y) and x <= start and y >= end) + this.character(start, end) and + not exists(int x, int y | this.charSet(x, y) and x <= start and y >= end) or this.group(start, end) or @@ -463,12 +452,8 @@ abstract class RegexString extends Expr { private predicate qualifier(int start, int end, boolean maybe_empty) { this.short_qualifier(start, end, maybe_empty) and not this.getChar(end) = "?" or - exists(int short_end | - this.short_qualifier(start, short_end, maybe_empty) | - if this.getChar(short_end) = "?" then - end = short_end+1 - else - end = short_end + exists(int short_end | this.short_qualifier(start, short_end, maybe_empty) | + if this.getChar(short_end) = "?" then end = short_end + 1 else end = short_end ) } @@ -479,26 +464,28 @@ abstract class RegexString extends Expr { this.getChar(start) = "*" and maybe_empty = true or this.getChar(start) = "?" and maybe_empty = true - ) and end = start + 1 + ) and + end = start + 1 or exists(int endin | end = endin + 1 | - this.getChar(start) = "{" and this.getChar(endin) = "}" and + this.getChar(start) = "{" and + this.getChar(endin) = "}" and end > start and - exists(string multiples | - multiples = this.getText().substring(start+1, endin) | + exists(string multiples | multiples = this.getText().substring(start + 1, endin) | multiples.regexpMatch("0*,[0-9]*") and maybe_empty = true or multiples.regexpMatch("0*[1-9][0-9]*,[0-9]*") and maybe_empty = false - ) - and + ) and not exists(int mid | this.getChar(mid) = "}" and - mid > start and mid < endin + mid > start and + mid < endin ) ) } - /** Whether the text in the range start,end is a qualified item, where item is a character, + /** + * Whether the text in the range start,end is a qualified item, where item is a character, * a character set or a group. */ predicate qualifiedItem(int start, int end, boolean maybe_empty) { @@ -520,19 +507,18 @@ abstract class RegexString extends Expr { ( start = 0 or this.group_start(_, start) or - this.isOptionDivider(start-1) - ) - and - this.item(start, end) or - ( - exists(int mid | - this.subsequence(start, mid) and - this.item(mid, end) - ) + this.isOptionDivider(start - 1) + ) and + this.item(start, end) + or + exists(int mid | + this.subsequence(start, mid) and + this.item(mid, end) ) } - /** Whether the text in the range start,end is a sequence of 1 or more items, where an item is a character, + /** + * Whether the text in the range start,end is a sequence of 1 or more items, where an item is a character, * a character set or a group. */ predicate sequence(int start, int end) { @@ -552,9 +538,12 @@ abstract class RegexString extends Expr { } private predicate item_end(int end) { - this.character(_, end) or - exists(int endm1 | this.isGroupEnd(endm1) and end = endm1 + 1) or - this.charSet(_, end) or + this.character(_, end) + or + exists(int endm1 | this.isGroupEnd(endm1) and end = endm1 + 1) + or + this.charSet(_, end) + or this.qualifier(_, end, _) } @@ -564,30 +553,36 @@ abstract class RegexString extends Expr { } private predicate subalternation(int start, int end, int item_start) { - this.sequenceOrQualified(start, end) and not this.isOptionDivider(start-1) and + this.sequenceOrQualified(start, end) and + not this.isOptionDivider(start - 1) and item_start = start or - start = end and not this.item_end(start) and this.isOptionDivider(end) and + start = end and + not this.item_end(start) and + this.isOptionDivider(end) and item_start = start or exists(int mid | this.subalternation(start, mid, _) and this.isOptionDivider(mid) and - item_start = mid+1 | + item_start = mid + 1 + | this.sequenceOrQualified(item_start, end) or not this.item_start(end) and end = item_start ) } - /** Whether the text in the range start,end is an alternation + /** + * Whether the text in the range start,end is an alternation */ predicate alternation(int start, int end) { this.top_level(start, end) and exists(int less | this.subalternation(start, less, _) and less < end) } - /** Whether the text in the range start,end is an alternation and the text in part_start, part_end is one of the + /** + * Whether the text in the range start,end is an alternation and the text in part_start, part_end is one of the * options in that alternation. */ predicate alternationOption(int start, int end, int part_start, int part_end) { @@ -599,22 +594,19 @@ abstract class RegexString extends Expr { private predicate firstPart(int start, int end) { start = 0 and end = this.getText().length() or - exists(int x | - this.firstPart(x, end) | + exists(int x | this.firstPart(x, end) | this.emptyMatchAtStartGroup(x, start) or this.qualifiedItem(x, start, true) or this.specialCharacter(x, start, "^") ) or - exists(int y | - this.firstPart(start, y) | + exists(int y | this.firstPart(start, y) | this.item(start, end) or this.qualifiedPart(start, end, y, _) ) or - exists(int x, int y | - this.firstPart(x, y) | + exists(int x, int y | this.firstPart(x, y) | this.groupContents(x, y, start, end) or this.alternationOption(x, y, start, end) @@ -625,8 +617,7 @@ abstract class RegexString extends Expr { private predicate lastPart(int start, int end) { start = 0 and end = this.getText().length() or - exists(int y | - this.lastPart(start, y) | + exists(int y | this.lastPart(start, y) | this.emptyMatchAtEndGroup(end, y) or this.qualifiedItem(end, y, true) or this.specialCharacter(end, y, "$") @@ -637,60 +628,52 @@ abstract class RegexString extends Expr { this.item(start, end) ) or - exists(int y | - this.lastPart(start, y) | - this.qualifiedPart(start, end, y, _) - ) + exists(int y | this.lastPart(start, y) | this.qualifiedPart(start, end, y, _)) or - exists(int x, int y | - this.lastPart(x, y) | + exists(int x, int y | this.lastPart(x, y) | this.groupContents(x, y, start, end) or this.alternationOption(x, y, start, end) ) } - /** Whether the item at [start, end) is one of the first items + /** + * Whether the item at [start, end) is one of the first items * to be matched. */ predicate firstItem(int start, int end) { ( - this.character(start, end) - or - this.qualifiedItem(start, end, _) - or - this.charSet(start, end) - ) - and + this.character(start, end) + or + this.qualifiedItem(start, end, _) + or + this.charSet(start, end) + ) and this.firstPart(start, end) } - /** Whether the item at [start, end) is one of the last items + /** + * Whether the item at [start, end) is one of the last items * to be matched. */ predicate lastItem(int start, int end) { ( - this.character(start, end) - or - this.qualifiedItem(start, end, _) - or - this.charSet(start, end) - ) - and + this.character(start, end) + or + this.qualifiedItem(start, end, _) + or + this.charSet(start, end) + ) and this.lastPart(start, end) } - } - /** A StrConst used as a regular expression */ class Regex extends RegexString { + Regex() { used_as_regex(this, _) } - Regex() { - used_as_regex(this, _) - } - - /** Gets a mode (if any) of this regular expression. Can be any of: + /** + * Gets a mode (if any) of this regular expression. Can be any of: * DEBUG * IGNORECASE * LOCALE @@ -705,5 +688,4 @@ class Regex extends RegexString { or result = this.getModeFromPrefix() } - -} \ No newline at end of file +} diff --git a/python/ql/src/semmle/python/security/ClearText.qll b/python/ql/src/semmle/python/security/ClearText.qll index ea4c33b7a9f..d08d2b03883 100644 --- a/python/ql/src/semmle/python/security/ClearText.qll +++ b/python/ql/src/semmle/python/security/ClearText.qll @@ -5,17 +5,12 @@ import semmle.python.dataflow.Files import semmle.python.web.Http module ClearTextStorage { - abstract class Sink extends TaintSink { - override predicate sinks(TaintKind kind) { - kind instanceof SensitiveData - } + override predicate sinks(TaintKind kind) { kind instanceof SensitiveData } } class CookieStorageSink extends Sink { - CookieStorageSink() { - any(CookieSet cookie).getValue() = this - } + CookieStorageSink() { any(CookieSet cookie).getValue() = this } } class FileStorageSink extends Sink { @@ -23,20 +18,17 @@ module ClearTextStorage { exists(CallNode call, AttrNode meth, string name | any(OpenFile fd).taints(meth.getObject(name)) and call.getFunction() = meth and - call.getAnArg() = this | + call.getAnArg() = this + | name = "write" ) } } - } module ClearTextLogging { - abstract class Sink extends TaintSink { - override predicate sinks(TaintKind kind) { - kind instanceof SensitiveData - } + override predicate sinks(TaintKind kind) { kind instanceof SensitiveData } } class PrintSink extends Sink { @@ -53,7 +45,8 @@ module ClearTextLogging { exists(CallNode call, AttrNode meth, string name | call.getFunction() = meth and meth.getObject(name).(NameNode).getId().matches("logg%") and - call.getAnArg() = this | + call.getAnArg() = this + | name = "error" or name = "warn" or name = "warning" or @@ -62,5 +55,4 @@ module ClearTextLogging { ) } } - } diff --git a/python/ql/src/semmle/python/security/Crypto.qll b/python/ql/src/semmle/python/security/Crypto.qll index 4a04b2082c6..06244851018 100644 --- a/python/ql/src/semmle/python/security/Crypto.qll +++ b/python/ql/src/semmle/python/security/Crypto.qll @@ -1,49 +1,32 @@ import python import semmle.python.security.TaintTracking - private import semmle.python.security.SensitiveData private import semmle.crypto.Crypto as CryptoLib - abstract class WeakCryptoSink extends TaintSink { - - override predicate sinks(TaintKind taint) { - taint instanceof SensitiveData - } + override predicate sinks(TaintKind taint) { taint instanceof SensitiveData } } /** Modeling the 'pycrypto' package https://github.com/dlitz/pycrypto (latest release 2013) */ module Pycrypto { - - ModuleValue cipher(string name) { - result = Module::named("Crypto.Cipher").attr(name) - } + ModuleValue cipher(string name) { result = Module::named("Crypto.Cipher").attr(name) } class CipherInstance extends TaintKind { - string name; CipherInstance() { - this = "Crypto.Cipher." + name and + this = "Crypto.Cipher." + name and exists(cipher(name)) } - string getName() { - result = name - } + string getName() { result = name } - CryptoLib::CryptographicAlgorithm getAlgorithm() { - result.getName() = name - } - - predicate isWeak() { - this.getAlgorithm().isWeak() - } + CryptoLib::CryptographicAlgorithm getAlgorithm() { result.getName() = name } + predicate isWeak() { this.getAlgorithm().isWeak() } } class CipherInstanceSource extends TaintSource { - CipherInstance instance; CipherInstanceSource() { @@ -53,18 +36,12 @@ module Pycrypto { ) } - override string toString() { - result = "Source of " + instance - } - - override predicate isSourceOf(TaintKind kind) { - kind = instance - } + override string toString() { result = "Source of " + instance } + override predicate isSourceOf(TaintKind kind) { kind = instance } } class PycryptoWeakCryptoSink extends WeakCryptoSink { - string name; PycryptoWeakCryptoSink() { @@ -77,36 +54,24 @@ module Pycrypto { ) } - override string toString() { - result = "Use of weak crypto algorithm " + name - } - + override string toString() { result = "Use of weak crypto algorithm " + name } } - } module Cryptography { - ModuleValue ciphers() { result = Module::named("cryptography.hazmat.primitives.ciphers") and result.isPackage() } class CipherClass extends ClassValue { - CipherClass() { - ciphers().attr("Cipher") = this - } + CipherClass() { ciphers().attr("Cipher") = this } } class AlgorithmClass extends ClassValue { + AlgorithmClass() { ciphers().attr("algorithms").attr(_) = this } - AlgorithmClass() { - ciphers().attr("algorithms").attr(_) = this - } - - string getAlgorithmName() { - result = this.declaredAttribute("name").(StringValue).getText() - } + string getAlgorithmName() { result = this.declaredAttribute("name").(StringValue).getText() } predicate isWeak() { exists(CryptoLib::CryptographicAlgorithm algo | @@ -117,61 +82,39 @@ module Cryptography { } class CipherInstance extends TaintKind { - AlgorithmClass cls; - CipherInstance() { - this = "cryptography.Cipher." + cls.getAlgorithmName() - } + CipherInstance() { this = "cryptography.Cipher." + cls.getAlgorithmName() } - AlgorithmClass getAlgorithm() { - result = cls - } + AlgorithmClass getAlgorithm() { result = cls } - predicate isWeak() { - cls.isWeak() - } + predicate isWeak() { cls.isWeak() } override TaintKind getTaintOfMethodResult(string name) { name = "encryptor" and result.(Encryptor).getAlgorithm() = this.getAlgorithm() } - } class CipherSource extends TaintSource { - - CipherSource() { - this.(CallNode).getFunction().pointsTo(any(CipherClass cls)) - } + CipherSource() { this.(CallNode).getFunction().pointsTo(any(CipherClass cls)) } override predicate isSourceOf(TaintKind kind) { this.(CallNode).getArg(0).pointsTo().getClass() = kind.(CipherInstance).getAlgorithm() } - override string toString() { - result = "cryptography.Cipher.source" - } - + override string toString() { result = "cryptography.Cipher.source" } } class Encryptor extends TaintKind { - AlgorithmClass cls; - Encryptor() { - this = "cryptography.encryptor." + cls.getAlgorithmName() - - } - - AlgorithmClass getAlgorithm() { - result = cls - } + Encryptor() { this = "cryptography.encryptor." + cls.getAlgorithmName() } + AlgorithmClass getAlgorithm() { result = cls } } class CryptographyWeakCryptoSink extends WeakCryptoSink { - CryptographyWeakCryptoSink() { exists(CallNode call, AttrNode method, Encryptor encryptor | call.getAnArg() = this and @@ -181,17 +124,11 @@ module Cryptography { ) } - override string toString() { - result = "Use of weak crypto algorithm" - } - + override string toString() { result = "Use of weak crypto algorithm" } } - - } private class CipherConfig extends TaintTracking::Configuration { - CipherConfig() { this = "Crypto cipher config" } override predicate isSource(TaintTracking::Source source) { @@ -199,5 +136,4 @@ private class CipherConfig extends TaintTracking::Configuration { or source instanceof Cryptography::CipherSource } - } diff --git a/python/ql/src/semmle/python/security/Exceptions.qll b/python/ql/src/semmle/python/security/Exceptions.qll index 143cf494bba..5344808caac 100644 --- a/python/ql/src/semmle/python/security/Exceptions.qll +++ b/python/ql/src/semmle/python/security/Exceptions.qll @@ -7,43 +7,31 @@ import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic -private Value traceback_function(string name) { - result = Module::named("traceback").attr(name) -} +private Value traceback_function(string name) { result = Module::named("traceback").attr(name) } /** * This represents information relating to an exception, for instance the * message, arguments or parts of the exception traceback. */ class ExceptionInfo extends StringKind { + ExceptionInfo() { this = "exception.info" } - ExceptionInfo() { - this = "exception.info" - } - - override string repr() { - result = "exception info" - } - + override string repr() { result = "exception info" } } -/** A class representing sources of information about +/** + * A class representing sources of information about * execution state exposed in tracebacks and the like. */ -abstract class ErrorInfoSource extends TaintSource {} +abstract class ErrorInfoSource extends TaintSource { } /** * This kind represents exceptions themselves. */ class ExceptionKind extends TaintKind { + ExceptionKind() { this = "exception.kind" } - ExceptionKind() { - this = "exception.kind" - } - - override string repr() { - result = "exception" - } + override string repr() { result = "exception" } override TaintKind getTaintOfAttribute(string name) { name = "args" and result instanceof ExceptionInfoSequence @@ -57,7 +45,6 @@ class ExceptionKind extends TaintKind { * `except` statement. */ class ExceptionSource extends ErrorInfoSource { - ExceptionSource() { exists(ClassValue cls | cls.getASuperType() = ClassValue::baseException() and @@ -67,13 +54,9 @@ class ExceptionSource extends ErrorInfoSource { this = any(ExceptStmt s).getName().getAFlowNode() } - override string toString() { - result = "exception.source" - } + override string toString() { result = "exception.source" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionKind - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionKind } } /** @@ -81,18 +64,14 @@ class ExceptionSource extends ErrorInfoSource { * for instance the contents of the `args` attribute, or the stack trace. */ class ExceptionInfoSequence extends SequenceKind { - ExceptionInfoSequence() { - this.getItem() instanceof ExceptionInfo - } + ExceptionInfoSequence() { this.getItem() instanceof ExceptionInfo } } - /** * Represents calls to functions in the `traceback` module that return * sequences of exception information. */ class CallToTracebackFunction extends ErrorInfoSource { - CallToTracebackFunction() { exists(string name | name = "extract_tb" or @@ -107,13 +86,9 @@ class CallToTracebackFunction extends ErrorInfoSource { ) } - override string toString() { - result = "exception.info.sequence.source" - } + override string toString() { result = "exception.info.sequence.source" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfoSequence - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfoSequence } } /** @@ -121,16 +96,9 @@ class CallToTracebackFunction extends ErrorInfoSource { * string of information about an exception. */ class FormattedTracebackSource extends ErrorInfoSource { + FormattedTracebackSource() { this = traceback_function("format_exc").getACall() } - FormattedTracebackSource() { - this = traceback_function("format_exc").getACall() - } + override string toString() { result = "exception.info.source" } - override string toString() { - result = "exception.info.source" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfo - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo } } diff --git a/python/ql/src/semmle/python/security/Paths.qll b/python/ql/src/semmle/python/security/Paths.qll index 846425ebca3..3c7bc657948 100644 --- a/python/ql/src/semmle/python/security/Paths.qll +++ b/python/ql/src/semmle/python/security/Paths.qll @@ -1,8 +1,6 @@ import semmle.python.dataflow.Implementation module TaintTrackingPaths { - - predicate edge(TaintTrackingNode src, TaintTrackingNode dest, string label) { exists(TaintTrackingNode source, TaintTrackingNode sink | source.getConfiguration().hasFlowPath(source, sink) and @@ -11,10 +9,8 @@ module TaintTrackingPaths { dest.getASuccessor*() = sink ) } - } - query predicate edges(TaintTrackingNode fromnode, TaintTrackingNode tonode) { TaintTrackingPaths::edge(fromnode, tonode, _) } diff --git a/python/ql/src/semmle/python/security/SQL.qll b/python/ql/src/semmle/python/security/SQL.qll index d1940ff05f5..a09d74134e6 100644 --- a/python/ql/src/semmle/python/security/SQL.qll +++ b/python/ql/src/semmle/python/security/SQL.qll @@ -1,4 +1,4 @@ import python import semmle.python.security.TaintTracking -abstract class SqlInjectionSink extends TaintSink {} +abstract class SqlInjectionSink extends TaintSink { } diff --git a/python/ql/src/semmle/python/security/SensitiveData.qll b/python/ql/src/semmle/python/security/SensitiveData.qll index 15b4c40f239..6e0b44d3c33 100644 --- a/python/ql/src/semmle/python/security/SensitiveData.qll +++ b/python/ql/src/semmle/python/security/SensitiveData.qll @@ -20,7 +20,6 @@ import semmle.python.web.HttpRequest * This is copied from the javascript library, but should be language independent. */ private module HeuristicNames { - /** * Gets a regular expression that identifies strings that may indicate the presence of secret * or trusted data. @@ -32,8 +31,8 @@ private module HeuristicNames { * user names or other account information. */ string maybeAccountInfo() { - result = "(?is).*acc(ou)?nt.*" or - result = "(?is).*(puid|username|userid).*" + result = "(?is).*acc(ou)?nt.*" or + result = "(?is).*(puid|username|userid).*" } /** @@ -41,8 +40,8 @@ private module HeuristicNames { * a password or an authorization key. */ string maybePassword() { - result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or - result = "(?is).*(auth(entication|ori[sz]ation)?)key.*" + result = "(?is).*pass(wd|word|code|phrase)(?!.*question).*" or + result = "(?is).*(auth(entication|ori[sz]ation)?)key.*" } /** @@ -51,7 +50,7 @@ private module HeuristicNames { */ string maybeCertificate() { result = "(?is).*(cert)(?!.*(format|name)).*" } - /** + /** * Gets a regular expression that identifies strings that may indicate the presence * of sensitive data, with `classification` describing the kind of sensitive data involved. */ @@ -78,35 +77,35 @@ private module HeuristicNames { name.regexpMatch(HeuristicNames::maybeSensitive(result)) and not name.regexpMatch(HeuristicNames::notSensitive()) } - } abstract class SensitiveData extends TaintKind { - bindingset[this] SensitiveData() { this = this } - } module SensitiveData { - class Secret extends SensitiveData { Secret() { this = "sensitive.data.secret" } + override string repr() { result = "a secret" } } class Id extends SensitiveData { Id() { this = "sensitive.data.id" } + override string repr() { result = "an ID" } } class Password extends SensitiveData { Password() { this = "sensitive.data.password" } + override string repr() { result = "a password" } } class Certificate extends SensitiveData { Certificate() { this = "sensitive.data.certificate" } + override string repr() { result = "a certificate or key" } } @@ -115,53 +114,35 @@ module SensitiveData { } abstract class Source extends TaintSource { - abstract string repr(); - } private class SensitiveCallSource extends Source { - SensitiveData data; SensitiveCallSource() { - exists(Value callee | - callee.getACall() = this | - data = fromFunction(callee) - ) + exists(Value callee | callee.getACall() = this | data = fromFunction(callee)) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "a call returning " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "a call returning " + data.repr() } } /** An access to a variable or property that might contain sensitive data. */ private class SensitiveVariableAccess extends SensitiveData::Source { - SensitiveData data; SensitiveVariableAccess() { data = HeuristicNames::getSensitiveDataForName(this.(AttrNode).getName()) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "an attribute or property containing " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "an attribute or property containing " + data.repr() } } private class SensitiveRequestParameter extends SensitiveData::Source { - SensitiveData data; SensitiveRequestParameter() { @@ -172,16 +153,10 @@ module SensitiveData { ) } - override predicate isSourceOf(TaintKind kind) { - kind = data - } - - override string repr() { - result = "a request parameter containing " + data.repr() - } + override predicate isSourceOf(TaintKind kind) { kind = data } + override string repr() { result = "a request parameter containing " + data.repr() } } - } //Backwards compatibility diff --git a/python/ql/src/semmle/python/security/TaintTracking.qll b/python/ql/src/semmle/python/security/TaintTracking.qll index c0bcbb6acb5..290fcc1ca71 100755 --- a/python/ql/src/semmle/python/security/TaintTracking.qll +++ b/python/ql/src/semmle/python/security/TaintTracking.qll @@ -1,2 +1,3 @@ /** For backwards compatibility */ + import semmle.python.dataflow.TaintTracking diff --git a/python/ql/src/semmle/python/security/flow/AnyCall.qll b/python/ql/src/semmle/python/security/flow/AnyCall.qll index 7a766bf25a5..de9526daf21 100644 --- a/python/ql/src/semmle/python/security/flow/AnyCall.qll +++ b/python/ql/src/semmle/python/security/flow/AnyCall.qll @@ -3,13 +3,7 @@ import semmle.python.security.strings.Basic /** Assume that taint flows from argument to result for *any* call */ class AnyCallStringFlow extends DataFlowExtension::DataFlowNode { + AnyCallStringFlow() { any(CallNode call).getAnArg() = this } - AnyCallStringFlow() { - any(CallNode call).getAnArg() = this - } - - override ControlFlowNode getASuccessorNode() { - result.(CallNode).getAnArg() = this - } - + override ControlFlowNode getASuccessorNode() { result.(CallNode).getAnArg() = this } } diff --git a/python/ql/src/semmle/python/security/injection/Deserialization.qll b/python/ql/src/semmle/python/security/injection/Deserialization.qll index 8d15ef2f8ac..14bf9d2233d 100644 --- a/python/ql/src/semmle/python/security/injection/Deserialization.qll +++ b/python/ql/src/semmle/python/security/injection/Deserialization.qll @@ -1,14 +1,8 @@ - import python import semmle.python.security.TaintTracking - /** `pickle.loads(untrusted)` vulnerability. */ abstract class DeserializationSink extends TaintSink { - bindingset[this] - DeserializationSink() { - this = this - } - + DeserializationSink() { this = this } } diff --git a/python/ql/src/semmle/python/security/injection/Exec.qll b/python/ql/src/semmle/python/security/injection/Exec.qll index 3830bbbd611..ee1621981c0 100644 --- a/python/ql/src/semmle/python/security/injection/Exec.qll +++ b/python/ql/src/semmle/python/security/injection/Exec.qll @@ -1,33 +1,30 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious Python code. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted - private FunctionObject exec_or_eval() { result = Object::builtin("exec") or result = Object::builtin("eval") } -/** A taint sink that represents an argument to exec or eval that is vulnerable to malicious input. +/** + * A taint sink that represents an argument to exec or eval that is vulnerable to malicious input. * The `vuln` in `exec(vuln)` or similar. */ class StringEvaluationNode extends TaintSink { - override string toString() { result = "exec or eval" } StringEvaluationNode() { - exists(Exec exec | - exec.getASubExpression().getAFlowNode() = this - ) + exists(Exec exec | exec.getASubExpression().getAFlowNode() = this) or exists(CallNode call | exec_or_eval().getACall() = call and @@ -35,8 +32,5 @@ class StringEvaluationNode extends TaintSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Marshal.qll b/python/ql/src/semmle/python/security/injection/Marshal.qll index 5ba361b1d94..274392c8b4f 100644 --- a/python/ql/src/semmle/python/security/injection/Marshal.qll +++ b/python/ql/src/semmle/python/security/injection/Marshal.qll @@ -1,26 +1,23 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious marshals. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization +private FunctionObject marshalLoads() { result = ModuleObject::named("marshal").attr("loads") } -private FunctionObject marshalLoads() { - result = ModuleObject::named("marshal").attr("loads") -} - - -/** A taint sink that is potentially vulnerable to malicious marshaled objects. - * The `vuln` in `marshal.loads(vuln)`. */ +/** + * A taint sink that is potentially vulnerable to malicious marshaled objects. + * The `vuln` in `marshal.loads(vuln)`. + */ class UnmarshalingNode extends DeserializationSink { - override string toString() { result = "unmarshaling vulnerability" } UnmarshalingNode() { @@ -30,8 +27,5 @@ class UnmarshalingNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Path.qll b/python/ql/src/semmle/python/security/injection/Path.qll index 31676430a45..833bd9f1960 100644 --- a/python/ql/src/semmle/python/security/injection/Path.qll +++ b/python/ql/src/semmle/python/security/injection/Path.qll @@ -1,28 +1,22 @@ import python - import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted -/** Prevents taint flowing through ntpath.normpath() +/** + * Prevents taint flowing through ntpath.normpath() * NormalizedPath below handles that case. */ class PathSanitizer extends Sanitizer { - - PathSanitizer() { - this = "path.sanitizer" - } + PathSanitizer() { this = "path.sanitizer" } override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { taint instanceof ExternalStringKind and abspath_call(node, _) } - } private FunctionObject abspath() { - exists(ModuleObject os_path | - ModuleObject::named("os").attr("path") = os_path - | + exists(ModuleObject os_path | ModuleObject::named("os").attr("path") = os_path | os_path.attr("abspath") = result or os_path.attr("normpath") = result @@ -31,15 +25,9 @@ private FunctionObject abspath() { /** A path that has been normalized, but not verified to be safe */ class NormalizedPath extends TaintKind { + NormalizedPath() { this = "normalized.path.injection" } - NormalizedPath() { - this = "normalized.path.injection" - } - - override string repr() { - result = "normalized path" - } - + override string repr() { result = "normalized path" } } private predicate abspath_call(CallNode call, ControlFlowNode arg) { @@ -47,39 +35,31 @@ private predicate abspath_call(CallNode call, ControlFlowNode arg) { arg = call.getArg(0) } - class AbsPath extends DataFlowExtension::DataFlowNode { + AbsPath() { abspath_call(_, this) } - AbsPath() { - abspath_call(_, this) + override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { + abspath_call(result, this) and + tokind instanceof NormalizedPath and + fromkind instanceof ExternalStringKind } - - override - ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) { - abspath_call(result, this) and tokind instanceof NormalizedPath and fromkind instanceof ExternalStringKind - } - } class NormalizedPathSanitizer extends Sanitizer { - - NormalizedPathSanitizer() { - this = "normalized.path.sanitizer" - } + NormalizedPathSanitizer() { this = "normalized.path.sanitizer" } override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof NormalizedPath and test.getTest().(CallNode).getFunction().(AttrNode).getName() = "startswith" and test.getSense() = true } - } -/** A taint sink that is vulnerable to malicious paths. +/** + * A taint sink that is vulnerable to malicious paths. * The `vuln` in `open(vuln)` and similar. */ class OpenNode extends TaintSink { - override string toString() { result = "argument to open()" } OpenNode() { @@ -94,10 +74,4 @@ class OpenNode extends TaintSink { or kind instanceof NormalizedPath } - } - - - - - diff --git a/python/ql/src/semmle/python/security/injection/Pickle.qll b/python/ql/src/semmle/python/security/injection/Pickle.qll index 7faefbdd685..2d56bc25f8e 100644 --- a/python/ql/src/semmle/python/security/injection/Pickle.qll +++ b/python/ql/src/semmle/python/security/injection/Pickle.qll @@ -1,17 +1,16 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious pickles. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization - private ModuleObject pickleModule() { result.getName() = "pickle" or @@ -20,13 +19,10 @@ private ModuleObject pickleModule() { result.getName() = "dill" } -private FunctionObject pickleLoads() { - result = pickleModule().attr("loads") -} +private FunctionObject pickleLoads() { result = pickleModule().attr("loads") } /** `pickle.loads(untrusted)` vulnerability. */ class UnpicklingNode extends DeserializationSink { - override string toString() { result = "unpickling untrusted data" } UnpicklingNode() { @@ -36,8 +32,5 @@ class UnpicklingNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/injection/Sql.qll b/python/ql/src/semmle/python/security/injection/Sql.qll index 07ee883ccf5..38c0eaec7d7 100644 --- a/python/ql/src/semmle/python/security/injection/Sql.qll +++ b/python/ql/src/semmle/python/security/injection/Sql.qll @@ -1,29 +1,27 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious SQL queries or parts of queries. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.SQL - private StringObject first_part(ControlFlowNode command) { command.(BinaryExprNode).getOp() instanceof Add and command.(BinaryExprNode).getLeft().refersTo(result) or - exists(CallNode call, SequenceObject seq | - call = command | + exists(CallNode call, SequenceObject seq | call = command | call = theStrType().lookupAttribute("join") and call.getArg(0).refersTo(seq) and seq.getInferredElement(0) = result ) or - command.(BinaryExprNode).getOp() instanceof Mod and + command.(BinaryExprNode).getOp() instanceof Mod and command.getNode().(StrConst).getLiteralObject() = result } @@ -32,52 +30,45 @@ predicate probable_sql_command(ControlFlowNode command, ControlFlowNode inject) exists(string prefix | inject = command.getAChild*() and first_part(command).getText().regexpMatch(" *" + prefix + ".*") - | + | prefix = "CREATE" or prefix = "SELECT" ) } -/** A taint kind representing a DB cursor. +/** + * A taint kind representing a DB cursor. * This will be overridden to provide specific kinds of DB cursor. */ abstract class DbCursor extends TaintKind { - bindingset[this] DbCursor() { any() } string getExecuteMethodName() { result = "execute" } - } -/** A part of a string that appears to be a SQL command and is thus +/** + * A part of a string that appears to be a SQL command and is thus * vulnerable to malicious input. */ class SimpleSqlStringInjection extends SqlInjectionSink { - override string toString() { result = "simple SQL string injection" } - SimpleSqlStringInjection() { - probable_sql_command(_, this) - } - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } + SimpleSqlStringInjection() { probable_sql_command(_, this) } + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } -/** A taint source representing sources of DB connections. +/** + * A taint source representing sources of DB connections. * This will be overridden to provide specific kinds of DB connection sources. */ -abstract class DbConnectionSource extends TaintSource { +abstract class DbConnectionSource extends TaintSource { } -} - -/** A taint sink that is vulnerable to malicious SQL queries. +/** + * A taint sink that is vulnerable to malicious SQL queries. * The `vuln` in `db.connection.execute(vuln)` and similar. */ class DbConnectionExecuteArgument extends SqlInjectionSink { - override string toString() { result = "db.connection.execute" } DbConnectionExecuteArgument() { @@ -88,9 +79,5 @@ class DbConnectionExecuteArgument extends SqlInjectionSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } - - diff --git a/python/ql/src/semmle/python/security/injection/Xml.qll b/python/ql/src/semmle/python/security/injection/Xml.qll index 7ab628b0085..080df3067d0 100644 --- a/python/ql/src/semmle/python/security/injection/Xml.qll +++ b/python/ql/src/semmle/python/security/injection/Xml.qll @@ -1,36 +1,26 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious XML objects. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization +private ModuleObject xmlElementTreeModule() { result.getName() = "xml.etree.ElementTree" } -private ModuleObject xmlElementTreeModule() { - result.getName() = "xml.etree.ElementTree" -} +private ModuleObject xmlMiniDomModule() { result.getName() = "xml.dom.minidom" } -private ModuleObject xmlMiniDomModule() { - result.getName() = "xml.dom.minidom" -} +private ModuleObject xmlPullDomModule() { result.getName() = "xml.dom.pulldom" } -private ModuleObject xmlPullDomModule() { - result.getName() = "xml.dom.pulldom" -} - -private ModuleObject xmlSaxModule() { - result.getName() = "xml.sax" -} +private ModuleObject xmlSaxModule() { result.getName() = "xml.sax" } private class ExpatParser extends TaintKind { - ExpatParser() { this = "expat.parser" } - } private FunctionObject expatCreateParseFunction() { @@ -38,18 +28,11 @@ private FunctionObject expatCreateParseFunction() { } private class ExpatCreateParser extends TaintSource { + ExpatCreateParser() { expatCreateParseFunction().getACall() = this } - ExpatCreateParser() { - expatCreateParseFunction().getACall() = this - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExpatParser } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExpatParser - } - - string toString() { - result = "expat.create.parser" - } + string toString() { result = "expat.create.parser" } } private FunctionObject xmlFromString() { @@ -64,30 +47,22 @@ private FunctionObject xmlFromString() { /** A (potentially) malicious XML string. */ class ExternalXmlString extends ExternalStringKind { - - ExternalXmlString() { - this = "external xml encoded object" - } - + ExternalXmlString() { this = "external xml encoded object" } } -/** A call to an XML library function that is potentially vulnerable to a +/** + * A call to an XML library function that is potentially vulnerable to a * specially crafted XML string. */ class XmlLoadNode extends DeserializationSink { - override string toString() { result = "xml.load vulnerability" } XmlLoadNode() { - exists(CallNode call | - call.getAnArg() = this | + exists(CallNode call | call.getAnArg() = this | xmlFromString().getACall() = call or any(ExpatParser parser).taints(call.getFunction().(AttrNode).getObject("Parse")) ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalXmlString - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalXmlString } } diff --git a/python/ql/src/semmle/python/security/injection/Yaml.qll b/python/ql/src/semmle/python/security/injection/Yaml.qll index d0c6b1b6723..3b0156b2812 100644 --- a/python/ql/src/semmle/python/security/injection/Yaml.qll +++ b/python/ql/src/semmle/python/security/injection/Yaml.qll @@ -1,25 +1,20 @@ -/** Provides class and predicates to track external data that +/** + * Provides class and predicates to track external data that * may represent malicious yaml-encoded objects. * * This module is intended to be imported into a taint-tracking query * to extend `TaintKind` and `TaintSink`. - * */ import python - import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.injection.Deserialization - -private FunctionObject yamlLoad() { - result = ModuleObject::named("yaml").attr("load") -} +private FunctionObject yamlLoad() { result = ModuleObject::named("yaml").attr("load") } /** `yaml.load(untrusted)` vulnerability. */ class YamlLoadNode extends DeserializationSink { - override string toString() { result = "yaml.load vulnerability" } YamlLoadNode() { @@ -29,8 +24,5 @@ class YamlLoadNode extends DeserializationSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } diff --git a/python/ql/src/semmle/python/security/strings/Basic.qll b/python/ql/src/semmle/python/security/strings/Basic.qll index bb3c871cd55..56756bb4846 100755 --- a/python/ql/src/semmle/python/security/strings/Basic.qll +++ b/python/ql/src/semmle/python/security/strings/Basic.qll @@ -1,15 +1,11 @@ import python private import Common - import semmle.python.security.TaintTracking /** An extensible kind of taint representing any kind of string. */ abstract class StringKind extends TaintKind { - bindingset[this] - StringKind() { - this = this - } + StringKind() { this = this } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { result = this and @@ -27,43 +23,44 @@ abstract class StringKind extends TaintKind { } override ClassValue getType() { - result = Value::named("bytes") or result = Value::named("str") or result = Value::named("unicode") + result = Value::named("bytes") or + result = Value::named("str") or + result = Value::named("unicode") } - } private class StringEqualitySanitizer extends Sanitizer { - StringEqualitySanitizer() { this = "string equality sanitizer" } /** The test `if untrusted == "KNOWN_VALUE":` sanitizes `untrusted` on its `true` edge. */ override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { taint instanceof StringKind and - exists(ControlFlowNode const, Cmpop op | - const.getNode() instanceof StrConst | + exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | ( test.getTest().(CompareNode).operands(const, op, _) or test.getTest().(CompareNode).operands(_, op, const) - ) and ( + ) and + ( op instanceof Eq and test.getSense() = true or op instanceof NotEq and test.getSense() = false ) ) } - } /* tonode = fromnode.xxx() where the call to xxx returns an identical or similar string */ private predicate str_method_call(ControlFlowNode fromnode, CallNode tonode) { - exists(string method_name | - tonode.getFunction().(AttrNode).getObject(method_name) = fromnode - | - method_name = "strip" or method_name = "format" or - method_name = "lstrip" or method_name = "rstrip" or - method_name = "ljust" or method_name = "rjust" or - method_name = "title" or method_name = "capitalize" + exists(string method_name | tonode.getFunction().(AttrNode).getObject(method_name) = fromnode | + method_name = "strip" or + method_name = "format" or + method_name = "lstrip" or + method_name = "rstrip" or + method_name = "ljust" or + method_name = "rjust" or + method_name = "title" or + method_name = "capitalize" ) } @@ -79,8 +76,10 @@ private predicate encode_decode(ControlFlowNode fromnode, CallNode tonode) { not func.getFunction().isMethod() and func.getACall() = tonode and tonode.getAnArg() = fromnode and - func.getName() = name | - name = "encode" or name = "decode" or + func.getName() = name + | + name = "encode" or + name = "decode" or name = "decodestring" ) } @@ -99,22 +98,19 @@ private predicate to_str(ControlFlowNode fromnode, CallNode tonode) { private predicate slice(ControlFlowNode fromnode, SubscriptNode tonode) { exists(Slice all | all = tonode.getIndex().getNode() and - not exists(all.getStart()) and not exists(all.getStop()) and + not exists(all.getStart()) and + not exists(all.getStop()) and tonode.getObject() = fromnode ) } /* tonode = os.path.join(..., fromnode, ...) */ private predicate os_path_join(ControlFlowNode fromnode, CallNode tonode) { - tonode = Value::named("os.path.join").getACall() - and tonode.getAnArg() = fromnode + tonode = Value::named("os.path.join").getACall() and + tonode.getAnArg() = fromnode } /** A kind of "taint", representing a dictionary mapping str->"taint" */ class StringDictKind extends DictKind { - - StringDictKind() { - this.getValue() instanceof StringKind - } - + StringDictKind() { this.getValue() instanceof StringKind } } diff --git a/python/ql/src/semmle/python/security/strings/Common.qll b/python/ql/src/semmle/python/security/strings/Common.qll index 6ac796d109b..404da271d78 100644 --- a/python/ql/src/semmle/python/security/strings/Common.qll +++ b/python/ql/src/semmle/python/security/strings/Common.qll @@ -1,12 +1,10 @@ import python - /* A call that returns a copy (or similar) of the argument */ predicate copy_call(ControlFlowNode fromnode, CallNode tonode) { tonode.getFunction().(AttrNode).getObject("copy") = fromnode or - exists(ModuleValue copy, string name | - name = "copy" or name = "deepcopy" | + exists(ModuleValue copy, string name | name = "copy" or name = "deepcopy" | copy.attr(name).(FunctionValue).getACall() = tonode and tonode.getArg(0) = fromnode ) diff --git a/python/ql/src/semmle/python/security/strings/External.qll b/python/ql/src/semmle/python/security/strings/External.qll index c8084552a5d..6a7261c4be3 100644 --- a/python/ql/src/semmle/python/security/strings/External.qll +++ b/python/ql/src/semmle/python/security/strings/External.qll @@ -206,7 +206,6 @@ class ExternalFileObject extends TaintKind { */ class UrlsplitUrlparseTempSanitizer extends Sanitizer { // TODO: remove this once we have better support for named tuples - UrlsplitUrlparseTempSanitizer() { this = "UrlsplitUrlparseTempSanitizer" } override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { @@ -238,9 +237,7 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer { /** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */ private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode tainted, boolean sense) { - exists(ControlFlowNode const, Cmpop op | - const.getNode() instanceof StrConst - | + exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst | ( cmp.operands(const, op, tainted) or @@ -257,7 +254,9 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer { /** holds for `in ["KNOWN_VALUE", ...]` on `true` edge, and `not in ["KNOWN_VALUE", ...]` on `false` edge */ private predicate test_in_const_seq(CompareNode cmp, ControlFlowNode tainted, boolean sense) { exists(SequenceNode const_seq, Cmpop op | - forall(ControlFlowNode elem | elem = const_seq.getAnElement() | elem.getNode() instanceof StrConst) + forall(ControlFlowNode elem | elem = const_seq.getAnElement() | + elem.getNode() instanceof StrConst + ) | cmp.operands(tainted, op, const_seq) and ( diff --git a/python/ql/src/semmle/python/security/strings/Untrusted.qll b/python/ql/src/semmle/python/security/strings/Untrusted.qll index 65e624aa1b7..6fa12668ada 100644 --- a/python/ql/src/semmle/python/security/strings/Untrusted.qll +++ b/python/ql/src/semmle/python/security/strings/Untrusted.qll @@ -1,14 +1,10 @@ import python import External - -/** A kind of taint representing an externally controlled string. +/** + * A kind of taint representing an externally controlled string. * This class is a simple sub-class of `ExternalStringKind`. */ class UntrustedStringKind extends ExternalStringKind { - - UntrustedStringKind() { - this = "externally controlled string" - } - + UntrustedStringKind() { this = "externally controlled string" } } diff --git a/python/ql/src/semmle/python/strings.qll b/python/ql/src/semmle/python/strings.qll index f94921aa263..e366d191669 100644 --- a/python/ql/src/semmle/python/strings.qll +++ b/python/ql/src/semmle/python/strings.qll @@ -9,23 +9,22 @@ predicate mapping_format(StrConst e) { } /* -MAPPING_KEY = "(\\([^)]+\\))?" -CONVERSION_FLAGS = "[#0\\- +]?" -MINIMUM_FIELD_WIDTH = "(\\*|[0-9]*)" -PRECISION = "(\\.(\\*|[0-9]*))?" -LENGTH_MODIFIER = "[hlL]?" -TYPE = "[bdiouxXeEfFgGcrs%]" -*/ + * MAPPING_KEY = "(\\([^)]+\\))?" + * CONVERSION_FLAGS = "[#0\\- +]?" + * MINIMUM_FIELD_WIDTH = "(\\*|[0-9]*)" + * PRECISION = "(\\.(\\*|[0-9]*))?" + * LENGTH_MODIFIER = "[hlL]?" + * TYPE = "[bdiouxXeEfFgGcrs%]" + */ -private -string conversion_specifier_string(StrConst e, int number, int position) { +private string conversion_specifier_string(StrConst e, int number, int position) { exists(string s, string REGEX | s = e.getText() | REGEX = "%(\\([^)]*\\))?[#0\\- +]*(\\*|[0-9]*)(\\.(\\*|[0-9]*))?(h|H|l|L)?[badiouxXeEfFgGcrs%]" and - result = s.regexpFind(REGEX, number, position)) + result = s.regexpFind(REGEX, number, position) + ) } -private -string conversion_specifier(StrConst e, int number) { +private string conversion_specifier(StrConst e, int number) { result = conversion_specifier_string(e, number, _) and result != "%%" } @@ -39,22 +38,17 @@ int illegal_conversion_specifier(StrConst e) { /** Gets the number of format items in a format string */ int format_items(StrConst e) { - result = count(int i | | conversion_specifier(e, i)) + - // a conversion specifier uses an extra item for each * - count(int i, int j | conversion_specifier(e, i).charAt(j) = "*") + result = + count(int i | | conversion_specifier(e, i)) + + // a conversion specifier uses an extra item for each * + count(int i, int j | conversion_specifier(e, i).charAt(j) = "*") } private string str(Expr e) { - result = ((Num)e).getN() + result = e.(Num).getN() or - result = "'" + ((StrConst)e).getText() + "'" + result = "'" + e.(StrConst).getText() + "'" } /** Gets a string representation of an expression more suited for embedding in message strings than .toString() */ -string repr(Expr e) { - if exists(str(e)) then - result = str(e) - else - result = e.toString() -} - +string repr(Expr e) { if exists(str(e)) then result = str(e) else result = e.toString() } diff --git a/python/ql/src/semmle/python/templates/PyxlTags.qll b/python/ql/src/semmle/python/templates/PyxlTags.qll index 3ab3f8980bc..07f4aa44e03 100644 --- a/python/ql/src/semmle/python/templates/PyxlTags.qll +++ b/python/ql/src/semmle/python/templates/PyxlTags.qll @@ -1,32 +1,22 @@ - - import python -/** A Tag in Pyxl (which gets converted to a call in Python). - * +/** + * A Tag in Pyxl (which gets converted to a call in Python). */ class PyxlTag extends Call { + PyxlTag() { pyxl_tag(this, _) } - PyxlTag() { - pyxl_tag(this, _) - } - - string getPyxlTagName() { - pyxl_tag(this, result) - } + string getPyxlTagName() { pyxl_tag(this, result) } /** Gets the pyxl or Python node that is enclosed by this one in the pyxl source */ - Expr getEnclosedNode() { - none() - } + Expr getEnclosedNode() { none() } /** Gets the Python code (if any) that is contained in this pyxl node */ Expr getEnclosedPythonCode() { result = this.getEnclosedNode() and not result instanceof PyxlTag or - result = ((PyxlTag)this.getEnclosedNode()).getEnclosedPythonCode() + result = this.getEnclosedNode().(PyxlTag).getEnclosedPythonCode() } - } private predicate pyxl_tag(Call c, string name) { @@ -39,53 +29,33 @@ private predicate pyxl_tag(Call c, string name) { } class PyxlHtmlTag extends PyxlTag { + PyxlHtmlTag() { this.getPyxlTagName().prefix(2) = "x_" } - PyxlHtmlTag() { - this.getPyxlTagName().prefix(2) = "x_" - } - - string getTagName() { - result = this.getPyxlTagName().suffix(2) - } + string getTagName() { result = this.getPyxlTagName().suffix(2) } /** Html tags get transformed into a call. This node is the callee function and the enclosed node is an argument. */ override Expr getEnclosedNode() { - exists(Call c | + exists(Call c | c.getFunc() = this and result = c.getAnArg() ) } - } class PyxlIfTag extends PyxlTag { + PyxlIfTag() { this.getPyxlTagName() = "_push_condition" } - PyxlIfTag() { - this.getPyxlTagName() = "_push_condition" - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } + override Expr getEnclosedNode() { result = this.getAnArg() } } class PyxlEndIfTag extends PyxlTag { + PyxlEndIfTag() { this.getPyxlTagName() = "_leave_if" } - PyxlEndIfTag() { - this.getPyxlTagName() = "_leave_if" - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } - + override Expr getEnclosedNode() { result = this.getAnArg() } } -class PyxlRawHtml extends PyxlTag{ - - PyxlRawHtml() { - this.getPyxlTagName() = "rawhtml" - } +class PyxlRawHtml extends PyxlTag { + PyxlRawHtml() { this.getPyxlTagName() = "rawhtml" } /** The text for this raw html, if it is simple text. */ string getText() { @@ -95,13 +65,7 @@ class PyxlRawHtml extends PyxlTag{ ) } - Expr getValue() { - result = this.getArg(0) - } - - override Expr getEnclosedNode() { - result = this.getAnArg() - } + Expr getValue() { result = this.getArg(0) } + override Expr getEnclosedNode() { result = this.getAnArg() } } - diff --git a/python/ql/src/semmle/python/templates/Templates.qll b/python/ql/src/semmle/python/templates/Templates.qll index 2aec12119a2..00aacd232a0 100644 --- a/python/ql/src/semmle/python/templates/Templates.qll +++ b/python/ql/src/semmle/python/templates/Templates.qll @@ -1,24 +1,15 @@ import python - -abstract class Template extends Module { - -} +abstract class Template extends Module { } class SpitfireTemplate extends Template { - - SpitfireTemplate() { - this.getKind() = "Spitfire template" - } - + SpitfireTemplate() { this.getKind() = "Spitfire template" } } class PyxlModule extends Template { - - PyxlModule() { + PyxlModule() { exists(Comment c | c.getLocation().getFile() = this.getFile() | c.getText().regexpMatch("# *coding.*pyxl.*") ) - } - + } } diff --git a/python/ql/src/semmle/python/types/Builtins.qll b/python/ql/src/semmle/python/types/Builtins.qll index e87e88c1c4b..a369218843e 100644 --- a/python/ql/src/semmle/python/types/Builtins.qll +++ b/python/ql/src/semmle/python/types/Builtins.qll @@ -1,14 +1,15 @@ import python class Builtin extends @py_cobject { - Builtin() { not ( /* @py_cobjects for modules which have a corresponding Python module */ - exists(@py_cobject mod_type | py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(this, mod_type)) and + exists(@py_cobject mod_type | + py_special_objects(mod_type, "ModuleType") and py_cobjecttypes(this, mod_type) + ) and exists(Module m | py_cobjectnames(this, m.getName())) - ) - and ( + ) and + ( /* Exclude unmatched builtin objects in the library trap files */ py_cobjectnames(this, _) or py_cobjecttypes(this, _) or @@ -17,9 +18,11 @@ class Builtin extends @py_cobject { } string toString() { - not this = undefinedVariable().asBuiltin() and not this = Builtin::unknown() and + not this = undefinedVariable().asBuiltin() and + not this = Builtin::unknown() and exists(Builtin type, string typename, string objname | - py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() | + py_cobjecttypes(this, type) and py_cobjectnames(this, objname) and typename = type.getName() + | result = typename + " " + objname ) } @@ -35,9 +38,7 @@ class Builtin extends @py_cobject { py_cmembers_versioned(this, name, result, major_version().toString()) } - Builtin getItem(int index) { - py_citems(this, index, result) - } + Builtin getItem(int index) { py_citems(this, index, result) } Builtin getBaseClass() { /* The extractor uses the special name ".super." to indicate the super class of a builtin class */ @@ -50,12 +51,7 @@ class Builtin extends @py_cobject { this.getBaseClass().inheritsFromType() } - string getName() { - if this.isStr() then - result = "str" - else - py_cobjectnames(this, result) - } + string getName() { if this.isStr() then result = "str" else py_cobjectnames(this, result) } private predicate isStr() { major_version() = 2 and this = Builtin::special("bytes") @@ -64,8 +60,10 @@ class Builtin extends @py_cobject { } predicate isClass() { - py_cobjecttypes(_, this) or - this = Builtin::unknownType() or + py_cobjecttypes(_, this) + or + this = Builtin::unknownType() + or exists(Builtin meta | meta.inheritsFromType() and py_cobjecttypes(this, meta)) } @@ -77,9 +75,7 @@ class Builtin extends @py_cobject { ) } - predicate isModule() { - this.getClass() = Builtin::special("ModuleType") - } + predicate isModule() { this.getClass() = Builtin::special("ModuleType") } predicate isMethod() { this.getClass() = Builtin::special("MethodDescriptorType") @@ -88,50 +84,42 @@ class Builtin extends @py_cobject { } int intValue() { - (this.getClass() = Builtin::special("int") or - this.getClass() = Builtin::special("long")) and + ( + this.getClass() = Builtin::special("int") or + this.getClass() = Builtin::special("long") + ) and result = this.getName().toInt() } float floatValue() { - (this.getClass() = Builtin::special("float")) and + this.getClass() = Builtin::special("float") and result = this.getName().toFloat() } string strValue() { - (this.getClass() = Builtin::special("unicode") or - this.getClass() = Builtin::special("bytes")) and + ( + this.getClass() = Builtin::special("unicode") or + this.getClass() = Builtin::special("bytes") + ) and exists(string quoted_string | - quoted_string = this.getName() - and + quoted_string = this.getName() and result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1) ) } - } module Builtin { - Builtin builtinModule() { py_special_objects(result, "builtin_module_2") and major_version() = 2 or py_special_objects(result, "builtin_module_3") and major_version() = 3 } - Builtin builtin(string name) { - result = builtinModule().getMember(name) - } + Builtin builtin(string name) { result = builtinModule().getMember(name) } - Builtin special(string name) { - py_special_objects(result, name) - } + Builtin special(string name) { py_special_objects(result, name) } - Builtin unknown() { - py_special_objects(result, "_1") - } + Builtin unknown() { py_special_objects(result, "_1") } - Builtin unknownType() { - py_special_objects(result, "_semmle_unknown_type") - } - -} \ No newline at end of file + Builtin unknownType() { py_special_objects(result, "_semmle_unknown_type") } +} diff --git a/python/ql/src/semmle/python/types/ClassObject.qll b/python/ql/src/semmle/python/types/ClassObject.qll index fc2b64bc32a..d48a9bddf22 100644 --- a/python/ql/src/semmle/python/types/ClassObject.qll +++ b/python/ql/src/semmle/python/types/ClassObject.qll @@ -6,22 +6,21 @@ private import semmle.python.pointsto.MRO private import semmle.python.types.Builtins private import semmle.python.objects.ObjectInternal - -/** A class whose instances represents Python classes. - * Instances of this class represent either builtin classes - * such as `list` or `str`, or program-defined Python classes +/** + * A class whose instances represents Python classes. + * Instances of this class represent either builtin classes + * such as `list` or `str`, or program-defined Python classes * present in the source code. - * - * Generally there is a one-to-one mapping between classes in - * the Python program and instances of this class in the database. - * However, that is not always the case. For example, dynamically + * + * Generally there is a one-to-one mapping between classes in + * the Python program and instances of this class in the database. + * However, that is not always the case. For example, dynamically * generated classes may share a single QL class instance. - * Also the existence of a class definition in the source code - * does not guarantee that such a class will ever exist in the + * Also the existence of a class definition in the source code + * does not guarantee that such a class will ever exist in the * running program. */ class ClassObject extends Object { - private ClassObjectInternal theClass() { result.getOrigin() = this or @@ -34,11 +33,10 @@ class ClassObject extends Object { } /** Gets the short (unqualified) name of this class */ - string getName() { - result = theClass().getName() - } + string getName() { result = theClass().getName() } - /** Gets the qualified name for this class. + /** + * Gets the qualified name for this class. * Should return the same name as the `__qualname__` attribute on classes in Python 3. */ string getQualifiedName() { @@ -48,19 +46,13 @@ class ClassObject extends Object { } /** Gets the nth base class of this class */ - Object getBaseType(int n) { - result = Types::getBase(theClass(), n).getSource() - } + Object getBaseType(int n) { result = Types::getBase(theClass(), n).getSource() } /** Gets a base class of this class */ - Object getABaseType() { - result = this.getBaseType(_) - } + Object getABaseType() { result = this.getBaseType(_) } /** Whether this class has a base class */ - predicate hasABase() { - exists(Types::getBase(theClass(), _)) - } + predicate hasABase() { exists(Types::getBase(theClass(), _)) } /** Gets a super class of this class (includes transitive super classes) */ ClassObject getASuperType() { @@ -68,35 +60,34 @@ class ClassObject extends Object { } /** Gets a super class of this class (includes transitive super classes) or this class */ - ClassObject getAnImproperSuperType() { - result = this.getABaseType*() - } + ClassObject getAnImproperSuperType() { result = this.getABaseType*() } - /** Whether this class is a new style class. - * A new style class is one that implicitly or explicitly inherits from `object`. */ - predicate isNewStyle() { - Types::isNewStyle(theClass()) - } + /** + * Whether this class is a new style class. + * A new style class is one that implicitly or explicitly inherits from `object`. + */ + predicate isNewStyle() { Types::isNewStyle(theClass()) } - /** Whether this class is an old style class. - * An old style class is one that does not inherit from `object`. */ - predicate isOldStyle() { - Types::isOldStyle(theClass()) - } + /** + * Whether this class is an old style class. + * An old style class is one that does not inherit from `object`. + */ + predicate isOldStyle() { Types::isOldStyle(theClass()) } - /** Whether this class is a legal exception class. - * What constitutes a legal exception class differs between major versions */ + /** + * Whether this class is a legal exception class. + * What constitutes a legal exception class differs between major versions + */ predicate isLegalExceptionType() { - not this.isNewStyle() or + not this.isNewStyle() + or this.getAnImproperSuperType() = theBaseExceptionType() or major_version() = 2 and this = theTupleType() } /** Gets the scope associated with this class, if it is not a builtin class */ - Class getPyClass() { - result.getClassObject() = this - } + Class getPyClass() { result.getClassObject() = this } /** Returns an attribute declared on this class (not on a super-class) */ Object declaredAttribute(string name) { @@ -111,8 +102,10 @@ class ClassObject extends Object { theClass().getClassDeclaration().declaresAttribute(name) } - /** Returns an attribute as it would be when looked up at runtime on this class. - * Will include attributes of super-classes */ + /** + * Returns an attribute as it would be when looked up at runtime on this class. + * Will include attributes of super-classes + */ Object lookupAttribute(string name) { exists(ObjectInternal val | theClass().lookup(name, val, _) and @@ -120,9 +113,7 @@ class ClassObject extends Object { ) } - ClassList getMro() { - result = Types::getMro(theClass()) - } + ClassList getMro() { result = Types::getMro(theClass()) } /** Looks up an attribute by searching this class' MRO starting at `start` */ Object lookupMro(ClassObject start, string name) { @@ -149,21 +140,20 @@ class ClassObject extends Object { ) } - /** Whether this class has a attribute named `name`, either declared or inherited.*/ - predicate hasAttribute(string name) { - theClass().hasAttribute(name) - } + /** Whether this class has a attribute named `name`, either declared or inherited. */ + predicate hasAttribute(string name) { theClass().hasAttribute(name) } - /** Whether it is impossible to know all the attributes of this class. Usually because it is - * impossible to calculate the full class hierarchy or because some attribute is too dynamic. */ + /** + * Whether it is impossible to know all the attributes of this class. Usually because it is + * impossible to calculate the full class hierarchy or because some attribute is too dynamic. + */ predicate unknowableAttributes() { /* True for a class with undeterminable superclasses, unanalysable metaclasses, or other confusions */ this.failedInference() or this.getMetaClass().failedInference() or - exists(Object base | - base = this.getABaseType() | + exists(Object base | base = this.getABaseType() | base.(ClassObject).unknowableAttributes() or not base instanceof ClassObject @@ -172,8 +162,7 @@ class ClassObject extends Object { /** Gets the metaclass for this class */ ClassObject getMetaClass() { - result = theClass().getClass().getSource() - and + result = theClass().getClass().getSource() and not this.failedInference() } @@ -183,35 +172,29 @@ class ClassObject extends Object { or exists(FunctionObject f, Raise r, Name ex | f = this.lookupAttribute(_) and - r.getScope() = f.getFunction() | + r.getScope() = f.getFunction() + | (r.getException() = ex or r.getException().(Call).getFunc() = ex) and (ex.getId() = "NotImplementedError" or ex.getId() = "NotImplemented") ) } - ControlFlowNode declaredMetaClass() { - result = this.getPyClass().getMetaClass().getAFlowNode() - } + ControlFlowNode declaredMetaClass() { result = this.getPyClass().getMetaClass().getAFlowNode() } - /** Has type inference failed to compute the full class hierarchy for this class for the reason given. */ - predicate failedInference(string reason) { - Types::failedInference(theClass(), reason) - } + /** Has type inference failed to compute the full class hierarchy for this class for the reason given. */ + predicate failedInference(string reason) { Types::failedInference(theClass(), reason) } - /** Has type inference failed to compute the full class hierarchy for this class */ - predicate failedInference() { - this.failedInference(_) - } + /** Has type inference failed to compute the full class hierarchy for this class */ + predicate failedInference() { this.failedInference(_) } - /** Gets an object which is the sole instance of this class, if this class is probably a singleton. + /** + * Gets an object which is the sole instance of this class, if this class is probably a singleton. * Note the 'probable' in the name; there is no guarantee that this class is in fact a singleton. - * It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject. */ + * It is guaranteed that getProbableSingletonInstance() returns at most one Object for each ClassObject. + */ Object getProbableSingletonInstance() { - exists(ControlFlowNode use, Expr origin | - use.refersTo(result, this, origin.getAFlowNode()) - | - this.hasStaticallyUniqueInstance() - and + exists(ControlFlowNode use, Expr origin | use.refersTo(result, this, origin.getAFlowNode()) | + this.hasStaticallyUniqueInstance() and /* Ensure that original expression will be executed only one. */ origin.getScope() instanceof ImportTimeScope and not exists(Expr outer | outer.getASubExpression+() = origin) @@ -225,9 +208,7 @@ class ClassObject extends Object { strictcount(SpecificInstanceInternal inst | inst.getClass() = theClass()) = 1 } - ImportTimeScope getImportTimeScope() { - result = this.getPyClass() - } + ImportTimeScope getImportTimeScope() { result = this.getPyClass() } override string toString() { this.isC() and result = "builtin-class " + this.getName() and not this = theUnknownType() @@ -236,84 +217,81 @@ class ClassObject extends Object { } /* Method Resolution Order */ - /** Returns the next class in the MRO of 'this' after 'sup' */ - ClassObject nextInMro(ClassObject sup) { - exists(ClassObjectInternal other | + ClassObject nextInMro(ClassObject sup) { + exists(ClassObjectInternal other | other.getSource() = sup and result = Types::getMro(theClass()).startingAt(other).getTail().getHead().getSource() ) and not this.failedInference() } - /** Gets the MRO for this class. ClassObject `sup` occurs at `index` in the list of classes. + /** + * Gets the MRO for this class. ClassObject `sup` occurs at `index` in the list of classes. * `this` has an index of `1`, the next class in the MRO has an index of `2`, and so on. */ - ClassObject getMroItem(int index) { - result = this.getMro().getItem(index).getSource() - } + ClassObject getMroItem(int index) { result = this.getMro().getItem(index).getSource() } /** Holds if this class has duplicate base classes */ predicate hasDuplicateBases() { - exists(ClassObject base, int i, int j | i != j and base = this.getBaseType(i) and base = this.getBaseType(j)) + exists(ClassObject base, int i, int j | + i != j and base = this.getBaseType(i) and base = this.getBaseType(j) + ) } /** Holds if this class is an iterable. */ - predicate isIterable() { - this.hasAttribute("__iter__") or this.hasAttribute("__getitem__") - } + predicate isIterable() { this.hasAttribute("__iter__") or this.hasAttribute("__getitem__") } /** Holds if this class is an iterator. */ predicate isIterator() { - this.hasAttribute("__iter__") and - (major_version() = 3 and this.hasAttribute("__next__") - or - /* Because 'next' is a common method name we need to check that an __iter__ - * method actually returns this class. This is not needed for Py3 as the - * '__next__' method exists to define a class as an iterator. - */ - major_version() = 2 and this.hasAttribute("next") and - exists(ClassObject other, FunctionObject iter | - other.declaredAttribute("__iter__") = iter | - iter.getAnInferredReturnType() = this - ) + this.hasAttribute("__iter__") and + ( + major_version() = 3 and this.hasAttribute("__next__") + or + /* + * Because 'next' is a common method name we need to check that an __iter__ + * method actually returns this class. This is not needed for Py3 as the + * '__next__' method exists to define a class as an iterator. + */ + + major_version() = 2 and + this.hasAttribute("next") and + exists(ClassObject other, FunctionObject iter | other.declaredAttribute("__iter__") = iter | + iter.getAnInferredReturnType() = this + ) ) or /* This will be redundant when we have C class information */ this = theGeneratorType() } - /** Holds if this class is an improper subclass of the other class. + /** + * Holds if this class is an improper subclass of the other class. * True if this is a sub-class of other or this is the same class as other. * * Equivalent to the Python builtin function issubclass(). */ - predicate isSubclassOf(ClassObject other) { - this = other or this.getASuperType() = other - } + predicate isSubclassOf(ClassObject other) { this = other or this.getASuperType() = other } /** Synonymous with isContainer(), retained for backwards compatibility. */ - predicate isCollection() { - this.isContainer() - } + predicate isCollection() { this.isContainer() } - /** Holds if this class is a container(). That is, does it have a __getitem__ method.*/ - predicate isContainer() { - exists(this.lookupAttribute("__getitem__")) - } + /** Holds if this class is a container(). That is, does it have a __getitem__ method. */ + predicate isContainer() { exists(this.lookupAttribute("__getitem__")) } /** Holds if this class is a mapping. */ predicate isMapping() { - exists(this.lookupAttribute("__getitem__")) - and + exists(this.lookupAttribute("__getitem__")) and not this.isSequence() } /** Holds if this class is probably a sequence. */ predicate isSequence() { - /* To determine whether something is a sequence or a mapping is not entirely clear, - * so we need to guess a bit. + /* + * To determine whether something is a sequence or a mapping is not entirely clear, + * so we need to guess a bit. */ + this.getAnImproperSuperType() = theTupleType() or this.getAnImproperSuperType() = theListType() @@ -330,18 +308,14 @@ class ClassObject extends Object { /* Does it have an index or __reversed__ method? */ this.isContainer() and ( - this.hasAttribute("index") or + this.hasAttribute("index") or this.hasAttribute("__reversed__") ) } - predicate isCallable() { - this.hasAttribute("__call__") - } + predicate isCallable() { this.hasAttribute("__call__") } - predicate isContextManager() { - this.hasAttribute("__enter__") and this.hasAttribute("__exit__") - } + predicate isContextManager() { this.hasAttribute("__enter__") and this.hasAttribute("__exit__") } predicate assignedInInit(string name) { exists(FunctionObject init | init = this.lookupAttribute("__init__") | @@ -353,17 +327,15 @@ class ClassObject extends Object { predicate unhashable() { this.lookupAttribute("__hash__") = theNoneObject() or - ((FunctionObject)this.lookupAttribute("__hash__")).neverReturns() + this.lookupAttribute("__hash__").(FunctionObject).neverReturns() } /** Holds if this class is a descriptor */ - predicate isDescriptorType() { - this.hasAttribute("__get__") - } + predicate isDescriptorType() { this.hasAttribute("__get__") } /** Holds if this class is an overriding descriptor */ predicate isOverridingDescriptorType() { - this.hasAttribute("__get__") and this.hasAttribute("__set__") + this.hasAttribute("__get__") and this.hasAttribute("__set__") } FunctionObject getAMethodCalledFromInit() { @@ -373,124 +345,80 @@ class ClassObject extends Object { ) } - override boolean booleanValue() { - result = true - } + override boolean booleanValue() { result = true } - /** Gets a call to this class. Note that the call may not create a new instance of + /** + * Gets a call to this class. Note that the call may not create a new instance of * this class, as that depends on the `__new__` method of this class. */ - CallNode getACall() { - result.getFunction().refersTo(this) - } - - override predicate notClass() { - none() - } + CallNode getACall() { result.getFunction().refersTo(this) } + override predicate notClass() { none() } } -/** The 'str' class. This is the same as the 'bytes' class for - * Python 2 and the 'unicode' class for Python 3 */ +/** + * The 'str' class. This is the same as the 'bytes' class for + * Python 2 and the 'unicode' class for Python 3 + */ ClassObject theStrType() { - if major_version() = 2 then - result = theBytesType() - else - result = theUnicodeType() + if major_version() = 2 then result = theBytesType() else result = theUnicodeType() } -private -Module theAbcModule() { - result.getName() = "abc" -} +private Module theAbcModule() { result.getName() = "abc" } ClassObject theAbcMetaClassObject() { /* Avoid using points-to and thus negative recursion */ - exists(Class abcmeta | - result.getPyClass() = abcmeta | + exists(Class abcmeta | result.getPyClass() = abcmeta | abcmeta.getName() = "ABCMeta" and abcmeta.getScope() = theAbcModule() ) } /* Common builtin classes */ - -/** The built-in class NoneType*/ -ClassObject theNoneType() { - result.asBuiltin() = Builtin::special("NoneType") -} +/** The built-in class NoneType */ +ClassObject theNoneType() { result.asBuiltin() = Builtin::special("NoneType") } /** The built-in class 'bool' */ -ClassObject theBoolType() { - result.asBuiltin() = Builtin::special("bool") -} +ClassObject theBoolType() { result.asBuiltin() = Builtin::special("bool") } /** The builtin class 'type' */ -ClassObject theTypeType() { - result.asBuiltin() = Builtin::special("type") -} +ClassObject theTypeType() { result.asBuiltin() = Builtin::special("type") } /** The builtin object ClassType (for old-style classes) */ -ClassObject theClassType() { - result.asBuiltin() = Builtin::special("ClassType") -} +ClassObject theClassType() { result.asBuiltin() = Builtin::special("ClassType") } /** The builtin object InstanceType (for old-style classes) */ -ClassObject theInstanceType() { - result.asBuiltin() = Builtin::special("InstanceType") -} +ClassObject theInstanceType() { result.asBuiltin() = Builtin::special("InstanceType") } /** The builtin class 'tuple' */ -ClassObject theTupleType() { - result.asBuiltin() = Builtin::special("tuple") -} +ClassObject theTupleType() { result.asBuiltin() = Builtin::special("tuple") } /** The builtin class 'int' */ -ClassObject theIntType() { - result.asBuiltin() = Builtin::special("int") -} +ClassObject theIntType() { result.asBuiltin() = Builtin::special("int") } /** The builtin class 'long' (Python 2 only) */ -ClassObject theLongType() { - result.asBuiltin() = Builtin::special("long") -} +ClassObject theLongType() { result.asBuiltin() = Builtin::special("long") } /** The builtin class 'float' */ -ClassObject theFloatType() { - result.asBuiltin() = Builtin::special("float") -} +ClassObject theFloatType() { result.asBuiltin() = Builtin::special("float") } /** The builtin class 'complex' */ -ClassObject theComplexType() { - result.asBuiltin() = Builtin::special("complex") -} +ClassObject theComplexType() { result.asBuiltin() = Builtin::special("complex") } /** The builtin class 'object' */ -ClassObject theObjectType() { - result.asBuiltin() = Builtin::special("object") -} +ClassObject theObjectType() { result.asBuiltin() = Builtin::special("object") } /** The builtin class 'list' */ -ClassObject theListType() { - result.asBuiltin() = Builtin::special("list") -} +ClassObject theListType() { result.asBuiltin() = Builtin::special("list") } /** The builtin class 'dict' */ - -ClassObject theDictType() { - result.asBuiltin() = Builtin::special("dict") -} +ClassObject theDictType() { result.asBuiltin() = Builtin::special("dict") } /** The builtin class 'Exception' */ - -ClassObject theExceptionType() { - result.asBuiltin() = Builtin::special("Exception") -} +ClassObject theExceptionType() { result.asBuiltin() = Builtin::special("Exception") } /** The builtin class for unicode. unicode in Python2, str in Python3 */ -ClassObject theUnicodeType() { - result.asBuiltin() = Builtin::special("unicode") -} +ClassObject theUnicodeType() { result.asBuiltin() = Builtin::special("unicode") } /** The builtin class '(x)range' */ ClassObject theRangeType() { @@ -500,24 +428,16 @@ ClassObject theRangeType() { } /** The builtin class for bytes. str in Python2, bytes in Python3 */ -ClassObject theBytesType() { - result.asBuiltin() = Builtin::special("bytes") -} +ClassObject theBytesType() { result.asBuiltin() = Builtin::special("bytes") } /** The builtin class 'set' */ -ClassObject theSetType() { - result.asBuiltin() = Builtin::special("set") -} +ClassObject theSetType() { result.asBuiltin() = Builtin::special("set") } /** The builtin class 'property' */ -ClassObject thePropertyType() { - result.asBuiltin() = Builtin::special("property") -} +ClassObject thePropertyType() { result.asBuiltin() = Builtin::special("property") } /** The builtin class 'BaseException' */ -ClassObject theBaseExceptionType() { - result.asBuiltin() = Builtin::special("BaseException") -} +ClassObject theBaseExceptionType() { result.asBuiltin() = Builtin::special("BaseException") } /** The class of builtin-functions */ ClassObject theBuiltinFunctionType() { @@ -525,54 +445,36 @@ ClassObject theBuiltinFunctionType() { } /** The class of Python functions */ -ClassObject thePyFunctionType() { - result.asBuiltin() = Builtin::special("FunctionType") -} +ClassObject thePyFunctionType() { result.asBuiltin() = Builtin::special("FunctionType") } /** The builtin class 'classmethod' */ -ClassObject theClassMethodType() { - result.asBuiltin() = Builtin::special("ClassMethod") -} +ClassObject theClassMethodType() { result.asBuiltin() = Builtin::special("ClassMethod") } /** The builtin class 'staticmethod' */ -ClassObject theStaticMethodType() { - result.asBuiltin() = Builtin::special("StaticMethod") -} +ClassObject theStaticMethodType() { result.asBuiltin() = Builtin::special("StaticMethod") } /** The class of modules */ -ClassObject theModuleType() { - result.asBuiltin() = Builtin::special("ModuleType") -} +ClassObject theModuleType() { result.asBuiltin() = Builtin::special("ModuleType") } /** The class of generators */ -ClassObject theGeneratorType() { - result.asBuiltin() = Builtin::special("generator") -} +ClassObject theGeneratorType() { result.asBuiltin() = Builtin::special("generator") } /** The builtin class 'TypeError' */ -ClassObject theTypeErrorType() { - result.asBuiltin() = Builtin::special("TypeError") -} +ClassObject theTypeErrorType() { result.asBuiltin() = Builtin::special("TypeError") } /** The builtin class 'AttributeError' */ -ClassObject theAttributeErrorType() { - result.asBuiltin() = Builtin::special("AttributeError") -} +ClassObject theAttributeErrorType() { result.asBuiltin() = Builtin::special("AttributeError") } /** The builtin class 'KeyError' */ -ClassObject theKeyErrorType() { - result.asBuiltin() = Builtin::special("KeyError") -} +ClassObject theKeyErrorType() { result.asBuiltin() = Builtin::special("KeyError") } /** The builtin class of bound methods */ -pragma [noinline] -ClassObject theBoundMethodType() { - result.asBuiltin() = Builtin::special("MethodType") -} +pragma[noinline] +ClassObject theBoundMethodType() { result.asBuiltin() = Builtin::special("MethodType") } /** The builtin class of builtin properties */ ClassObject theGetSetDescriptorType() { - result.asBuiltin() = Builtin::special("GetSetDescriptorType") + result.asBuiltin() = Builtin::special("GetSetDescriptorType") } /** The method descriptor class */ @@ -582,27 +484,19 @@ ClassObject theMethodDescriptorType() { /** The class of builtin properties */ ClassObject theBuiltinPropertyType() { - /* This is CPython specific */ + /* This is CPython specific */ result.isC() and result.getName() = "getset_descriptor" } /** The builtin class 'IOError' */ -ClassObject theIOErrorType() { - result = Object::builtin("IOError") -} +ClassObject theIOErrorType() { result = Object::builtin("IOError") } /** The builtin class 'super' */ -ClassObject theSuperType() { - result = Object::builtin("super") -} +ClassObject theSuperType() { result = Object::builtin("super") } /** The builtin class 'StopIteration' */ -ClassObject theStopIterationType() { - result = Object::builtin("StopIteration") -} +ClassObject theStopIterationType() { result = Object::builtin("StopIteration") } /** The builtin class 'NotImplementedError' */ -ClassObject theNotImplementedErrorType() { - result = Object::builtin("NotImplementedError") -} +ClassObject theNotImplementedErrorType() { result = Object::builtin("NotImplementedError") } diff --git a/python/ql/src/semmle/python/types/Descriptors.qll b/python/ql/src/semmle/python/types/Descriptors.qll index 949ff1d4266..f190f9a6434 100644 --- a/python/ql/src/semmle/python/types/Descriptors.qll +++ b/python/ql/src/semmle/python/types/Descriptors.qll @@ -1,13 +1,9 @@ import python private import semmle.python.objects.ObjectInternal - -/** A class method object. Either a decorated function or an explicit call to classmethod(f) */ +/** A class method object. Either a decorated function or an explicit call to classmethod(f) */ class ClassMethodObject extends Object { - - ClassMethodObject() { - any(ClassMethodObjectInternal cm).getOrigin() = this - } + ClassMethodObject() { any(ClassMethodObjectInternal cm).getOrigin() = this } FunctionObject getFunction() { exists(ClassMethodObjectInternal cm | @@ -16,18 +12,12 @@ class ClassMethodObject extends Object { ) } - CallNode getACall() { - result = this.getFunction().getACall() - } - + CallNode getACall() { result = this.getFunction().getACall() } } -/** A static method object. Either a decorated function or an explicit call to staticmethod(f) */ +/** A static method object. Either a decorated function or an explicit call to staticmethod(f) */ class StaticMethodObject extends Object { - - StaticMethodObject() { - any(StaticMethodObjectInternal sm).getOrigin() = this - } + StaticMethodObject() { any(StaticMethodObjectInternal sm).getOrigin() = this } FunctionObject getFunction() { exists(StaticMethodObjectInternal sm | @@ -35,6 +25,4 @@ class StaticMethodObject extends Object { result = sm.getFunction().getSource() ) } - } - diff --git a/python/ql/src/semmle/python/types/Exceptions.qll b/python/ql/src/semmle/python/types/Exceptions.qll index 387fa43100d..c6aa76a1919 100644 --- a/python/ql/src/semmle/python/types/Exceptions.qll +++ b/python/ql/src/semmle/python/types/Exceptions.qll @@ -1,6 +1,6 @@ /** * Analysis of exception raising and handling. - * + * * In order to make this useful we make a number of assumptions. These are: * 1. Typing errors (TypeError, NameError, AttributeError) are assumed to occur only if: * a) Explicitly raised, e.g. raise TypeError() @@ -15,7 +15,6 @@ import python /** Subset of ControlFlowNodes which might raise an exception */ class RaisingNode extends ControlFlowNode { - RaisingNode() { exists(this.getAnExceptionalSuccessor()) or @@ -24,63 +23,58 @@ class RaisingNode extends ControlFlowNode { /** Gets the CFG node for the exception, if and only if this RaisingNode is an explicit raise */ ControlFlowNode getExceptionNode() { - exists(Raise r | - r = this.getNode() and result.getNode() = r.getRaised() and + exists(Raise r | + r = this.getNode() and + result.getNode() = r.getRaised() and result.getBasicBlock().dominates(this.getBasicBlock()) ) } - private predicate quits() { - this.(CallNode).getFunction().refersTo(Object::quitter(_)) - } + private predicate quits() { this.(CallNode).getFunction().refersTo(Object::quitter(_)) } - /** Gets the type of an exception that may be raised - * at this control flow node */ + /** + * Gets the type of an exception that may be raised + * at this control flow node + */ ClassObject getARaisedType() { result = this.localRaisedType() or - exists(FunctionObject func | - this = func.getACall() | - result = func.getARaisedType() - ) + exists(FunctionObject func | this = func.getACall() | result = func.getARaisedType()) or result = systemExitRaise() } pragma[noinline] - private ClassObject systemExitRaise() { - this.quits() and result = Object::builtin("SystemExit") - } + private ClassObject systemExitRaise() { this.quits() and result = Object::builtin("SystemExit") } - pragma [noinline, nomagic] + pragma[noinline, nomagic] private ClassObject localRaisedType() { - result.isSubclassOf(theBaseExceptionType()) - and + result.isSubclassOf(theBaseExceptionType()) and ( - exists(ControlFlowNode ex | - ex = this.getExceptionNode() and - (ex.refersTo(result) or ex.refersTo(_, result, _)) - ) - or - this.getNode() instanceof ImportExpr and result = Object::builtin("ImportError") - or - this.getNode() instanceof Print and result = theIOErrorType() - or - exists(ExceptFlowNode except | - except = this.getAnExceptionalSuccessor() and - except.handles(result) and - result = this.innateException() - ) - or - not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) - and - sequence_or_mapping(this) and result = theLookupErrorType() - or - this.read_write_call() and result = theIOErrorType() + exists(ControlFlowNode ex | + ex = this.getExceptionNode() and + (ex.refersTo(result) or ex.refersTo(_, result, _)) + ) + or + this.getNode() instanceof ImportExpr and result = Object::builtin("ImportError") + or + this.getNode() instanceof Print and result = theIOErrorType() + or + exists(ExceptFlowNode except | + except = this.getAnExceptionalSuccessor() and + except.handles(result) and + result = this.innateException() + ) + or + not exists(ExceptFlowNode except | except = this.getAnExceptionalSuccessor()) and + sequence_or_mapping(this) and + result = theLookupErrorType() + or + this.read_write_call() and result = theIOErrorType() ) } - pragma [noinline] + pragma[noinline] ClassObject innateException() { this.getNode() instanceof Attribute and result = theAttributeErrorType() or @@ -91,30 +85,29 @@ class RaisingNode extends ControlFlowNode { this.getNode() instanceof Subscript and result = theKeyErrorType() } - /** Whether this control flow node raises an exception, - * but the type of the exception it raises cannot be inferred. */ + /** + * Whether this control flow node raises an exception, + * but the type of the exception it raises cannot be inferred. + */ predicate raisesUnknownType() { /* read/write calls are assumed to raise IOError (OSError for Py3) */ - not this.read_write_call() - and + not this.read_write_call() and ( - /* Call to an unknown object */ - this.getNode() instanceof Call and not exists(FunctionObject func | this = func.getACall()) - and not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known)) - or - this.getNode() instanceof Exec - or - /* Call to a function raising an unknown type */ - exists(FunctionObject func | - this = func.getACall() | - func.raisesUnknownType() - ) + /* Call to an unknown object */ + this.getNode() instanceof Call and + not exists(FunctionObject func | this = func.getACall()) and + not exists(ClassObject known | this.(CallNode).getFunction().refersTo(known)) + or + this.getNode() instanceof Exec + or + /* Call to a function raising an unknown type */ + exists(FunctionObject func | this = func.getACall() | func.raisesUnknownType()) ) } private predicate read_write_call() { exists(string mname | mname = this.(CallNode).getFunction().(AttrNode).getName() | - mname = "read" or mname = "write" + mname = "read" or mname = "write" ) } @@ -143,23 +136,26 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType() and succ = this.getAnExceptionalSuccessor() and - ( + ( /* An 'except' that handles raised and there is no more previous handler */ - ((ExceptFlowNode)succ).handles(raised) and - not exists(ExceptFlowNode other, StmtList s, int i, int j | - not other = succ and other.handles(raised) and - s.getItem(i) = succ.getNode() and s.getItem(j) = other.getNode() - | + succ.(ExceptFlowNode).handles(raised) and + not exists(ExceptFlowNode other, StmtList s, int i, int j | + not other = succ and + other.handles(raised) and + s.getItem(i) = succ.getNode() and + s.getItem(j) = other.getNode() + | j < i ) or /* Any successor that is not an 'except', provided that 'raised' is not handled by a different successor. */ - (not ((ExceptFlowNode)this.getAnExceptionalSuccessor()).handles(raised) and - not succ instanceof ExceptFlowNode) + not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) and + not succ instanceof ExceptFlowNode ) } - /** Whether this exceptional exit is viable. That is, is it + /** + * Whether this exceptional exit is viable. That is, is it * plausible that the scope `s` can be exited with exception `raised` * at this point. */ @@ -167,46 +163,48 @@ class RaisingNode extends ControlFlowNode { raised.isLegalExceptionType() and raised = this.getARaisedType() and this.isExceptionalExit(s) and - not ((ExceptFlowNode)this.getAnExceptionalSuccessor()).handles(raised) + not this.getAnExceptionalSuccessor().(ExceptFlowNode).handles(raised) } - } /** Is this a sequence or mapping subscript x[i]? */ -private predicate sequence_or_mapping(RaisingNode r) { - r.getNode() instanceof Subscript -} +private predicate sequence_or_mapping(RaisingNode r) { r.getNode() instanceof Subscript } private predicate current_exception(ClassObject ex, BasicBlock b) { exists(RaisingNode r | r.viableExceptionEdge(b.getNode(0), ex) and not b.getNode(0) instanceof ExceptFlowNode ) or - exists(BasicBlock prev | + exists(BasicBlock prev | current_exception(ex, prev) and exists(ControlFlowNode pred, ControlFlowNode succ | - pred = prev.getLastNode() and succ = b.getNode(0) | - pred.getASuccessor() = succ and - (/* Normal control flow */ - not pred.getAnExceptionalSuccessor() = succ or - /* Re-raise the current exception, propagating to the successor */ - pred instanceof ReraisingNode) + pred = prev.getLastNode() and succ = b.getNode(0) + | + pred.getASuccessor() = succ and + ( + /* Normal control flow */ + not pred.getAnExceptionalSuccessor() = succ + or + /* Re-raise the current exception, propagating to the successor */ + pred instanceof ReraisingNode + ) ) ) } private predicate unknown_current_exception(BasicBlock b) { exists(RaisingNode r | - r.raisesUnknownType() and + r.raisesUnknownType() and r.getAnExceptionalSuccessor() = b.getNode(0) and not b.getNode(0) instanceof ExceptFlowNode ) or - exists(BasicBlock prev | + exists(BasicBlock prev | unknown_current_exception(prev) and exists(ControlFlowNode pred, ControlFlowNode succ | - pred = prev.getLastNode() and succ = b.getNode(0) | - pred.getASuccessor() = succ and + pred = prev.getLastNode() and succ = b.getNode(0) + | + pred.getASuccessor() = succ and (not pred.getAnExceptionalSuccessor() = succ or pred instanceof ReraisingNode) ) ) @@ -214,9 +212,10 @@ private predicate unknown_current_exception(BasicBlock b) { /** INTERNAL -- Use FunctionObject.getARaisedType() instead */ predicate scope_raises(ClassObject ex, Scope s) { - exists(BasicBlock b | + exists(BasicBlock b | current_exception(ex, b) and - b.getLastNode().isExceptionalExit(s) | + b.getLastNode().isExceptionalExit(s) + | b.getLastNode() instanceof ReraisingNode ) or @@ -225,9 +224,10 @@ predicate scope_raises(ClassObject ex, Scope s) { /** INTERNAL -- Use FunctionObject.raisesUnknownType() instead */ predicate scope_raises_unknown(Scope s) { - exists(BasicBlock b | - b.getLastNode() instanceof ReraisingNode - and b.getLastNode().isExceptionalExit(s) | + exists(BasicBlock b | + b.getLastNode() instanceof ReraisingNode and + b.getLastNode().isExceptionalExit(s) + | unknown_current_exception(b) ) or @@ -237,95 +237,88 @@ predicate scope_raises_unknown(Scope s) { ) } - /** ControlFlowNode for an 'except' statement. */ class ExceptFlowNode extends ControlFlowNode { - - ExceptFlowNode() { - this.getNode() instanceof ExceptStmt - } + ExceptFlowNode() { this.getNode() instanceof ExceptStmt } ControlFlowNode getType() { exists(ExceptStmt ex | this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and result = ex.getType().getAFlowNode() + ex = this.getNode() and + result = ex.getType().getAFlowNode() ) } ControlFlowNode getName() { exists(ExceptStmt ex | this.getBasicBlock().dominates(result.getBasicBlock()) and - ex = this.getNode() and result = ex.getName().getAFlowNode() + ex = this.getNode() and + result = ex.getName().getAFlowNode() ) } private predicate handledObject_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { this.getType().refersTo(obj, cls, origin) or - exists(Object tup | - this.handledObject_objectapi(tup, theTupleType(), _) | + exists(Object tup | this.handledObject_objectapi(tup, theTupleType(), _) | element_from_tuple_objectapi(tup).refersTo(obj, cls, origin) ) } - + private predicate handledObject(Value val, ClassValue cls, ControlFlowNode origin) { val.getClass() = cls and ( this.getType().pointsTo(val, origin) or - exists(TupleValue tup | - this.handledObject(tup, ClassValue::tuple(), _) | + exists(TupleValue tup | this.handledObject(tup, ClassValue::tuple(), _) | val = tup.getItem(_) and origin = val.getOrigin() ) ) } /** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */ - pragma [noinline] + pragma[noinline] predicate handledException_objectapi(Object obj, ClassObject cls, ControlFlowNode origin) { this.handledObject_objectapi(obj, cls, origin) and not cls = theTupleType() or - not exists(this.getNode().(ExceptStmt).getType()) and obj = theBaseExceptionType() and cls = theTypeType() and + not exists(this.getNode().(ExceptStmt).getType()) and + obj = theBaseExceptionType() and + cls = theTypeType() and origin = this } - + /** Gets the inferred type(s) that are handled by this node, splitting tuples if possible. */ - pragma [noinline] + pragma[noinline] predicate handledException(Value val, ClassValue cls, ControlFlowNode origin) { this.handledObject(val, cls, origin) and not cls = ClassValue::tuple() or - not exists(this.getNode().(ExceptStmt).getType()) and val = ClassValue::baseException() and cls = ClassValue::type() and + not exists(this.getNode().(ExceptStmt).getType()) and + val = ClassValue::baseException() and + cls = ClassValue::type() and origin = this } - - /** Whether this `except` handles `cls` */ predicate handles(ClassObject cls) { - exists(ClassObject handled | - this.handledException_objectapi(handled, _, _) | + exists(ClassObject handled | this.handledException_objectapi(handled, _, _) | cls.getAnImproperSuperType() = handled ) } - } private ControlFlowNode element_from_tuple_objectapi(Object tuple) { - exists(Tuple t | - t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode() - ) + exists(Tuple t | t = tuple.getOrigin() and result = t.getAnElt().getAFlowNode()) } -/** A Reraising node is the node at the end of a finally block (on the exceptional branch) +/** + * A Reraising node is the node at the end of a finally block (on the exceptional branch) * that reraises the current exception. */ class ReraisingNode extends RaisingNode { - ReraisingNode() { not this.getNode() instanceof Raise and in_finally(this) and - forall(ControlFlowNode succ | - succ = this.getASuccessor() | + forall(ControlFlowNode succ | succ = this.getASuccessor() | succ = this.getAnExceptionalSuccessor() ) } @@ -337,17 +330,12 @@ class ReraisingNode extends RaisingNode { b.getNode(_) = this ) } - } private predicate in_finally(ControlFlowNode n) { - exists(Stmt f | - exists(Try t | f = t.getAFinalstmt()) | - f = n.getNode() + exists(Stmt f | exists(Try t | f = t.getAFinalstmt()) | + f = n.getNode() or f.containsInScope(n.getNode()) ) } - - - diff --git a/python/ql/src/semmle/python/types/Extensions.qll b/python/ql/src/semmle/python/types/Extensions.qll index b6fb3f519ac..7e1e7c5ab85 100644 --- a/python/ql/src/semmle/python/types/Extensions.qll +++ b/python/ql/src/semmle/python/types/Extensions.qll @@ -1,6 +1,7 @@ -/** This library allows custom extensions to the points-to analysis to incorporate +/** + * This library allows custom extensions to the points-to analysis to incorporate * custom domain knowledge into the points-to analysis. - * + * * This should be considered an advance feature. Modifying the points-to analysis * can cause queries to give strange and misleading results, if not done with care. * @@ -14,71 +15,58 @@ private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext private import semmle.python.objects.TObject private import semmle.python.web.HttpConstants - /* Make ObjectInternal visible to save extra imports in user code */ import semmle.python.objects.ObjectInternal abstract class PointsToExtension extends @py_flow_node { - string toString() { result = "PointsToExtension with missing toString" } abstract predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin); - } - /* Legacy API */ - -/* Custom Facts. This extension mechanism allows you to add custom +/* + * Custom Facts. This extension mechanism allows you to add custom * sources of data to the points-to analysis. */ /** DEPRECATED -- Use PointsToExtension instead */ -deprecated abstract class CustomPointsToFact extends @py_flow_node { - +abstract deprecated class CustomPointsToFact extends @py_flow_node { string toString() { result = "CustomPointsToFact with missing toString" } abstract predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin); - } /* For backwards compatibility */ class FinalCustomPointsToFact = CustomPointsToFact; -deprecated abstract class CustomPointsToOriginFact extends CustomPointsToFact { - +abstract deprecated class CustomPointsToOriginFact extends CustomPointsToFact { abstract predicate pointsTo(Object value, ClassObject cls); override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) { this.pointsTo(value, cls) and origin = this and context.appliesTo(this) } - } /* Custom points-to fact with inferred class */ -deprecated abstract class CustomPointsToObjectFact extends CustomPointsToFact { - +abstract deprecated class CustomPointsToObjectFact extends CustomPointsToFact { abstract predicate pointsTo(Object value); override predicate pointsTo(Context context, Object value, ClassObject cls, ControlFlowNode origin) { this.pointsTo(value) and cls = simple_types(value) and origin = this and context.appliesTo(this) } - } - /** DEPRECATED -- Unsupported; do not use */ -deprecated abstract class CustomPointsToAttribute extends Object { - - abstract predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin); - +abstract deprecated class CustomPointsToAttribute extends Object { + abstract predicate attributePointsTo( + string name, Object value, ClassObject cls, ControlFlowNode origin + ); } /* An example */ - /** Any variable iterating over range or xrange must be an integer */ class RangeIterationVariableFact extends PointsToExtension { - RangeIterationVariableFact() { exists(For f, ControlFlowNode iterable | iterable.getBasicBlock().dominates(this.(ControlFlowNode).getBasicBlock()) and @@ -96,13 +84,10 @@ class RangeIterationVariableFact extends PointsToExtension { origin = this and context.appliesTo(this) } - } /* bottle module route constants */ - class BottleRoutePointToExtension extends PointsToExtension { - string name; BottleRoutePointToExtension() { @@ -110,7 +95,7 @@ class BottleRoutePointToExtension extends PointsToExtension { defn.getScope().(Module).getName() = "bottle" and this = defn.getValue() and name = defn.(NameNode).getId() - | + | name = "route" or name = httpVerbLower() ) @@ -123,19 +108,19 @@ class BottleRoutePointToExtension extends PointsToExtension { origin = orig.asCfgNodeOrHere(this) ) } - } /* Python 3.6+ regex module constants */ - string short_flag(string flag) { - (flag = "ASCII" or - flag = "IGNORECASE" or - flag = "LOCALE" or - flag = "UNICODE" or - flag = "MULTILINE" or - flag = "TEMPLATE") - and result = flag.prefix(1) + ( + flag = "ASCII" or + flag = "IGNORECASE" or + flag = "LOCALE" or + flag = "UNICODE" or + flag = "MULTILINE" or + flag = "TEMPLATE" + ) and + result = flag.prefix(1) or flag = "DOTALL" and result = "S" or @@ -143,11 +128,11 @@ string short_flag(string flag) { } class ReModulePointToExtension extends PointsToExtension { - string name; ReModulePointToExtension() { - exists(ModuleObjectInternal re | re.getName() = "re" and + exists(ModuleObjectInternal re | + re.getName() = "re" and PointsTo::pointsTo(this.(AttrNode).getObject(name), _, re, _) ) } @@ -158,27 +143,21 @@ class ReModulePointToExtension extends PointsToExtension { sre_constants.getName() = "sre_constants" and sre_constants.attribute("SRE_FLAG_" + flag, value, orig) and origin = orig.asCfgNodeOrHere(this) - ) - and pointsTo_helper(context) - } - - pragma [noinline] - private predicate pointsTo_helper(Context context) { - context.appliesTo(this) + ) and + pointsTo_helper(context) } + pragma[noinline] + private predicate pointsTo_helper(Context context) { context.appliesTo(this) } } private class BackwardCompatiblePointToExtension extends PointsToExtension { - - BackwardCompatiblePointToExtension() { - this instanceof CustomPointsToFact - } + BackwardCompatiblePointToExtension() { this instanceof CustomPointsToFact } override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) { exists(Object obj, ClassObject cls | this.(CustomPointsToFact).pointsTo(context, obj, cls, origin) - | + | value.getBuiltin() = obj or obj instanceof ControlFlowNode and @@ -193,13 +172,14 @@ private class BackwardCompatiblePointToExtension extends PointsToExtension { additionalAttribute(owner, name, value, origin) ) } - } -private predicate additionalAttribute(ObjectInternal owner, string name, ObjectInternal value, ControlFlowNode origin) { +private predicate additionalAttribute( + ObjectInternal owner, string name, ObjectInternal value, ControlFlowNode origin +) { exists(Object obj, ClassObject cls | owner.getSource().(CustomPointsToAttribute).attributePointsTo(name, obj, cls, origin) - | + | value.getBuiltin() = obj or obj instanceof ControlFlowNode and @@ -209,4 +189,3 @@ private predicate additionalAttribute(ObjectInternal owner, string name, ObjectI ) ) } - diff --git a/python/ql/src/semmle/python/types/FunctionObject.qll b/python/ql/src/semmle/python/types/FunctionObject.qll index 6c1ed1bf93a..6c1db531184 100644 --- a/python/ql/src/semmle/python/types/FunctionObject.qll +++ b/python/ql/src/semmle/python/types/FunctionObject.qll @@ -9,22 +9,13 @@ private import semmle.python.types.Builtins /** A function object, whether written in Python or builtin */ abstract class FunctionObject extends Object { + CallableValue theCallable() { result.(ObjectInternal).getSource() = this } - CallableValue theCallable() { - result.(ObjectInternal).getSource() = this - } + predicate isOverridingMethod() { exists(Object f | this.overrides(f)) } - predicate isOverridingMethod() { - exists(Object f | this.overrides(f)) - } + predicate isOverriddenMethod() { exists(Object f | f.overrides(this)) } - predicate isOverriddenMethod() { - exists(Object f | f.overrides(this)) - } - - Function getFunction() { - result = ((CallableExpr)this.getOrigin()).getInnerScope() - } + Function getFunction() { result = this.getOrigin().(CallableExpr).getInnerScope() } /** This function always returns None, meaning that its return value should be disregarded */ abstract predicate isProcedure(); @@ -39,17 +30,13 @@ abstract class FunctionObject extends Object { abstract predicate raisesUnknownType(); /** Use descriptiveString() instead. */ - deprecated string prettyString() { - result = this.descriptiveString() - } + deprecated string prettyString() { result = this.descriptiveString() } /** Gets a longer, more descriptive version of toString() */ abstract string descriptiveString(); /** Gets a call-site from where this function is called as a function */ - CallNode getAFunctionCall() { - result.getFunction().inferredValue() = theCallable() - } + CallNode getAFunctionCall() { result.getFunction().inferredValue() = theCallable() } /** Gets a call-site from where this function is called as a method */ CallNode getAMethodCall() { @@ -60,36 +47,36 @@ abstract class FunctionObject extends Object { } /** Gets a call-site from where this function is called */ - ControlFlowNode getACall() { - result = theCallable().getACall() - } + ControlFlowNode getACall() { result = theCallable().getACall() } /** Gets a call-site from where this function is called, given the `context` */ ControlFlowNode getACall(Context caller_context) { result = theCallable().getACall(caller_context) } - /** Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. + /** + * Gets the `ControlFlowNode` that will be passed as the nth argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the zeroth argument. - */ + */ ControlFlowNode getArgumentForCall(CallNode call, int n) { result = theCallable().getArgumentForCall(call, n) } - /** Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. + /** + * Gets the `ControlFlowNode` that will be passed as the named argument to `this` when called at `call`. * This predicate will correctly handle `x.y()`, treating `x` as the self argument. - */ + */ ControlFlowNode getNamedArgumentForCall(CallNode call, string name) { result = theCallable().getNamedArgumentForCall(call, name) } /** Whether this function never returns. This is an approximation. */ - predicate neverReturns() { - theCallable().neverReturns() - } + predicate neverReturns() { theCallable().neverReturns() } - /** Whether this is a "normal" method, that is, it is exists as a class attribute - * which is not wrapped and not the __new__ method. */ + /** + * Whether this is a "normal" method, that is, it is exists as a class attribute + * which is not wrapped and not the __new__ method. + */ predicate isNormalMethod() { exists(ClassObject cls, string name | cls.declaredAttribute(name) = this and @@ -112,7 +99,8 @@ abstract class FunctionObject extends Object { ) } - /** Gets the qualified name for this function object. + /** + * Gets the qualified name for this function object. * Should return the same name as the `__qualname__` attribute on functions in Python 3. */ abstract string getQualifiedName(); @@ -128,59 +116,39 @@ abstract class FunctionObject extends Object { } /** Gets a class that this function may return */ - ClassObject getAnInferredReturnType() { - result = this.(BuiltinCallable).getAReturnType() - } - - predicate isAbstract() { - this.getARaisedType() = theNotImplementedErrorType() - } + ClassObject getAnInferredReturnType() { result = this.(BuiltinCallable).getAReturnType() } + predicate isAbstract() { this.getARaisedType() = theNotImplementedErrorType() } } class PyFunctionObject extends FunctionObject { + PyFunctionObject() { any(PythonFunctionObjectInternal f).getOrigin() = this } - PyFunctionObject() { - any(PythonFunctionObjectInternal f).getOrigin() = this - } - - override string toString() { - result = "Function " + this.getName() - } + override string toString() { result = "Function " + this.getName() } override string getName() { - result = ((FunctionExpr)this.getOrigin()).getName() + result = this.getOrigin().(FunctionExpr).getName() or this.getOrigin() instanceof Lambda and result = "lambda" } /** Whether this function is a procedure, that is, it has no explicit return statement and is not a generator function */ - override predicate isProcedure() { - this.getFunction().isProcedure() - } + override predicate isProcedure() { this.getFunction().isProcedure() } - override ClassObject getARaisedType() { - scope_raises(result, this.getFunction()) - } + override ClassObject getARaisedType() { scope_raises(result, this.getFunction()) } - override predicate raisesUnknownType() { - scope_raises_unknown(this.getFunction()) - } + override predicate raisesUnknownType() { scope_raises_unknown(this.getFunction()) } /** Gets a control flow node corresponding to the value of a return statement */ - ControlFlowNode getAReturnedNode() { - result = this.getFunction().getAReturnValueFlowNode() - } + ControlFlowNode getAReturnedNode() { result = this.getFunction().getAReturnValueFlowNode() } override string descriptiveString() { - if this.getFunction().isMethod() then ( - exists(Class cls | - this.getFunction().getScope() = cls | + if this.getFunction().isMethod() + then + exists(Class cls | this.getFunction().getScope() = cls | result = "method " + this.getQualifiedName() ) - ) else ( - result = "function " + this.getQualifiedName() - ) + else result = "function " + this.getQualifiedName() } override int minParameters() { @@ -193,16 +161,13 @@ class PyFunctionObject extends FunctionObject { override int maxParameters() { exists(Function f | f = this.getFunction() and - if exists(f.getVararg()) then - result = 2147483647 // INT_MAX - else - result = count(f.getAnArg()) + if exists(f.getVararg()) + then result = 2147483647 // INT_MAX + else result = count(f.getAnArg()) ) } - override string getQualifiedName() { - result = this.getFunction().getQualifiedName() - } + override string getQualifiedName() { result = this.getFunction().getQualifiedName() } predicate unconditionallyReturnsParameter(int n) { exists(SsaVariable pvar | @@ -219,7 +184,9 @@ class PyFunctionObject extends FunctionObject { /** Factored out to help join ordering */ private predicate implicitlyReturns(Object none_, ClassObject noneType) { - noneType = theNoneType() and not this.getFunction().isGenerator() and none_ = theNoneObject() and + noneType = theNoneType() and + not this.getFunction().isGenerator() and + none_ = theNoneObject() and ( not exists(this.getAReturnedNode()) and exists(this.getFunction().getANormalExit()) or @@ -231,9 +198,10 @@ class PyFunctionObject extends FunctionObject { override ClassObject getAnInferredReturnType() { this.getFunction().isGenerator() and result = theGeneratorType() or - not this.neverReturns() and not this.getFunction().isGenerator() and + not this.neverReturns() and + not this.getFunction().isGenerator() and ( - this.(PyFunctionObject).getAReturnedNode().refersTo( _, result, _) + this.(PyFunctionObject).getAReturnedNode().refersTo(_, result, _) or this.implicitlyReturns(_, result) ) @@ -242,18 +210,13 @@ class PyFunctionObject extends FunctionObject { ParameterDefinition getParameter(int n) { result.getDefiningNode().getNode() = this.getFunction().getArg(n) } - } abstract class BuiltinCallable extends FunctionObject { - abstract ClassObject getAReturnType(); override predicate isProcedure() { - forex(ClassObject rt | - rt = this.getAReturnType() | - rt = theNoneType() - ) + forex(ClassObject rt | rt = this.getAReturnType() | rt = theNoneType()) } abstract override string getQualifiedName(); @@ -261,18 +224,13 @@ abstract class BuiltinCallable extends FunctionObject { override ControlFlowNode getArgumentForCall(CallNode call, int n) { call = this.getACall() and result = call.getArg(n) } - } class BuiltinMethodObject extends BuiltinCallable { - - BuiltinMethodObject() { - any(BuiltinMethodObjectInternal m).getBuiltin() = this - } + BuiltinMethodObject() { any(BuiltinMethodObjectInternal m).getBuiltin() = this } override string getQualifiedName() { - exists(ClassObject cls | - cls.asBuiltin().getMember(_) = this.asBuiltin() | + exists(ClassObject cls | cls.asBuiltin().getMember(_) = this.asBuiltin() | result = cls.getName() + "." + this.getName() ) or @@ -280,17 +238,11 @@ class BuiltinMethodObject extends BuiltinCallable { result = this.getName() } - override string descriptiveString() { - result = "builtin-method " + this.getQualifiedName() - } + override string descriptiveString() { result = "builtin-method " + this.getQualifiedName() } - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } - override string toString() { - result = "Builtin-method " + this.getName() - } + override string toString() { result = "Builtin-method " + this.getName() } override ClassObject getARaisedType() { /* Information is unavailable for C code in general */ @@ -302,41 +254,23 @@ class BuiltinMethodObject extends BuiltinCallable { any() } - override int minParameters() { - none() - } + override int minParameters() { none() } - override int maxParameters() { - none() - } - - override ClassObject getAReturnType() { - ext_rettype(this.asBuiltin(), result.asBuiltin()) - } + override int maxParameters() { none() } + override ClassObject getAReturnType() { ext_rettype(this.asBuiltin(), result.asBuiltin()) } } class BuiltinFunctionObject extends BuiltinCallable { + BuiltinFunctionObject() { any(BuiltinFunctionObjectInternal f).getBuiltin() = this } - BuiltinFunctionObject() { - any(BuiltinFunctionObjectInternal f).getBuiltin() = this - } + override string getName() { result = this.asBuiltin().getName() } - override string getName() { - result = this.asBuiltin().getName() - } + override string getQualifiedName() { result = this.getName() } - override string getQualifiedName() { - result = this.getName() - } + override string toString() { result = "Builtin-function " + this.getName() } - override string toString() { - result = "Builtin-function " + this.getName() - } - - override string descriptiveString() { - result = "builtin-function " + this.getName() - } + override string descriptiveString() { result = "builtin-function " + this.getName() } override ClassObject getARaisedType() { /* Information is unavailable for C code in general */ @@ -349,16 +283,19 @@ class BuiltinFunctionObject extends BuiltinCallable { } override ClassObject getAReturnType() { - /* Enumerate the types of a few builtin functions, that the CPython analysis misses. - */ + /* + * Enumerate the types of a few builtin functions, that the CPython analysis misses. + */ + this = Object::builtin("hex") and result = theStrType() or this = Object::builtin("oct") and result = theStrType() or this = Object::builtin("intern") and result = theStrType() or - /* Fix a few minor inaccuracies in the CPython analysis */ - ext_rettype(this.asBuiltin(), result.asBuiltin()) and not ( + /* Fix a few minor inaccuracies in the CPython analysis */ + ext_rettype(this.asBuiltin(), result.asBuiltin()) and + not ( this = Object::builtin("__import__") and result = theNoneType() or this = Object::builtin("compile") and result = theNoneType() @@ -369,63 +306,37 @@ class BuiltinFunctionObject extends BuiltinCallable { ) } - override int minParameters() { - none() - } - - override int maxParameters() { - none() - } + override int minParameters() { none() } + override int maxParameters() { none() } } /** DEPRECATED -- Use `Object::builtin("apply")` instead. */ -deprecated Object theApplyFunction() { - result = Object::builtin("apply") -} +deprecated Object theApplyFunction() { result = Object::builtin("apply") } /** DEPRECATED -- Use `Object::builtin("hasattr")` instead. */ -deprecated Object theHasattrFunction() { - result = Object::builtin("hasattr") -} +deprecated Object theHasattrFunction() { result = Object::builtin("hasattr") } /** DEPRECATED -- Use `Object::builtin("len")` instead. */ -deprecated Object theLenFunction() { - result = Object::builtin("len") -} +deprecated Object theLenFunction() { result = Object::builtin("len") } /** DEPRECATED -- Use `Object::builtin("format")` instead. */ -deprecated Object theFormatFunction() { - result = Object::builtin("format") -} +deprecated Object theFormatFunction() { result = Object::builtin("format") } /** DEPRECATED -- Use `Object::builtin("open")` instead. */ -deprecated Object theOpenFunction() { - result = Object::builtin("open") -} +deprecated Object theOpenFunction() { result = Object::builtin("open") } /** DEPRECATED -- Use `Object::builtin("print")` instead. */ -deprecated Object thePrintFunction() { - result = Object::builtin("print") -} +deprecated Object thePrintFunction() { result = Object::builtin("print") } /** DEPRECATED -- Use `Object::builtin("input")` instead. */ -deprecated Object theInputFunction() { - result = Object::builtin("input") -} +deprecated Object theInputFunction() { result = Object::builtin("input") } /** DEPRECATED -- Use `Object::builtin("locals")` instead. */ -deprecated Object theLocalsFunction() { - result = Object::builtin("locals") -} +deprecated Object theLocalsFunction() { result = Object::builtin("locals") } /** DEPRECATED -- Use `Object::builtin("globals")()` instead. */ -deprecated Object theGlobalsFunction() { - result = Object::builtin("globals") -} +deprecated Object theGlobalsFunction() { result = Object::builtin("globals") } /** DEPRECATED -- Use `Object::builtin("sysExit()` instead. */ -deprecated Object theExitFunctionObject() { - result = ModuleObject::named("sys").attr("exit") -} - +deprecated Object theExitFunctionObject() { result = ModuleObject::named("sys").attr("exit") } diff --git a/python/ql/src/semmle/python/types/ImportTime.qll b/python/ql/src/semmle/python/types/ImportTime.qll index 0a9e7c9d145..a35ed9d122a 100644 --- a/python/ql/src/semmle/python/types/ImportTime.qll +++ b/python/ql/src/semmle/python/types/ImportTime.qll @@ -1,18 +1,18 @@ import python -/** An ImportTimeScope is any scope that is not nested within a function and will thus be executed if its - * enclosing module is imported. +/** + * An ImportTimeScope is any scope that is not nested within a function and will thus be executed if its + * enclosing module is imported. * Note however, that if a scope is not an ImportTimeScope it may still be executed at import time. * This is an artificial approximation, which is necessary for static analysis. */ class ImportTimeScope extends Scope { - - ImportTimeScope() { - not this.getEnclosingScope*() instanceof Function - } + ImportTimeScope() { not this.getEnclosingScope*() instanceof Function } - /** Whether this scope explicitly defines 'name'. - * Does not cover implicit definitions be import * */ + /** + * Whether this scope explicitly defines 'name'. + * Does not cover implicit definitions be import * + */ pragma[nomagic] predicate definesName(string name) { exists(SsaVariable var | name = var.getId() and var.getAUse() = this.getANormalExit()) @@ -31,5 +31,4 @@ class ImportTimeScope extends Scope { result.getScope() = this.getEnclosingModule() and var.getId() = result.getId() } - } diff --git a/python/ql/src/semmle/python/types/ModuleKind.qll b/python/ql/src/semmle/python/types/ModuleKind.qll index abb39626ff1..1509bac24e2 100644 --- a/python/ql/src/semmle/python/types/ModuleKind.qll +++ b/python/ql/src/semmle/python/types/ModuleKind.qll @@ -11,14 +11,16 @@ private predicate is_normal_module(ModuleObject m) { } private predicate is_script(ModuleObject m) { - not is_normal_module(m) and ( + not is_normal_module(m) and + ( m.getModule().getFile().getExtension() != ".py" or - exists(If i, Name name, StrConst main, Cmpop op | + exists(If i, Name name, StrConst main, Cmpop op | i.getScope() = m.getModule() and op instanceof Eq and i.getTest().(Compare).compares(name, op, main) and - name.getId() = "__name__" and main.getText() = "__main__" + name.getId() = "__name__" and + main.getText() = "__main__" ) ) } @@ -29,7 +31,8 @@ private predicate is_plugin(ModuleObject m) { not is_script(m) } -/** Gets the kind for module `m` will be one of +/** + * Gets the kind for module `m` will be one of * "module", "script" or "plugin" */ string getKindForModule(ModuleObject m) { diff --git a/python/ql/src/semmle/python/types/ModuleObject.qll b/python/ql/src/semmle/python/types/ModuleObject.qll index 0590636edfd..3b5d15c41b1 100644 --- a/python/ql/src/semmle/python/types/ModuleObject.qll +++ b/python/ql/src/semmle/python/types/ModuleObject.qll @@ -4,7 +4,6 @@ private import semmle.python.objects.ObjectInternal private import semmle.python.types.ModuleKind abstract class ModuleObject extends Object { - ModuleValue theModule() { result.(PythonModuleObjectInternal).getSourceModule() = this.getModule() or @@ -14,18 +13,12 @@ abstract class ModuleObject extends Object { } /** Gets the scope corresponding to this module, if this is a Python module */ - Module getModule() { - none() - } + Module getModule() { none() } /** Gets the source scope corresponding to this module, if this is a Python module */ - Module getSourceModule() { - none() - } + Module getSourceModule() { none() } - Container getPath() { - none() - } + Container getPath() { none() } /** Gets the name of this scope */ abstract string getName(); @@ -37,23 +30,20 @@ abstract class ModuleObject extends Object { result = this.getModule().toString() } - /** Gets the named attribute of this module. Using attributeRefersTo() instead + /** + * Gets the named attribute of this module. Using attributeRefersTo() instead * may provide better results for presentation. - * */ - Object getAttribute(string name) { - this.attributeRefersTo(name, result, _) - } + */ + Object getAttribute(string name) { this.attributeRefersTo(name, result, _) } - /** Gets the named attribute of this module. - * Synonym for `getAttribute(name)` */ - pragma [inline] - final Object attr(string name) { - result = this.getAttribute(name) - } + /** + * Gets the named attribute of this module. + * Synonym for `getAttribute(name)` + */ + pragma[inline] + final Object attr(string name) { result = this.getAttribute(name) } - predicate hasAttribute(string name) { - theModule().hasAttribute(name) - } + predicate hasAttribute(string name) { theModule().hasAttribute(name) } predicate attributeRefersTo(string name, Object obj, ControlFlowNode origin) { exists(ObjectInternal val, CfgOrigin valorig | @@ -78,150 +68,111 @@ abstract class ModuleObject extends Object { result.getName() = this.getName().regexpReplaceAll("\\.[^.]*$", "") } - /** Whether this module "exports" `name`. That is, whether using `import *` on this module - * will result in `name` being added to the namespace. */ - predicate exports(string name) { - theModule().exports(name) - } + /** + * Whether this module "exports" `name`. That is, whether using `import *` on this module + * will result in `name` being added to the namespace. + */ + predicate exports(string name) { theModule().exports(name) } /** - * Whether the complete set of names "exported" by this module can be accurately determined - * - * DEPRECATED: Use ModuleValue::hasCompleteExportInfo instead - */ - deprecated abstract predicate exportsComplete(); + * Whether the complete set of names "exported" by this module can be accurately determined + * + * DEPRECATED: Use ModuleValue::hasCompleteExportInfo instead + */ + abstract deprecated predicate exportsComplete(); /** Gets the short name of the module. For example the short name of module x.y.z is 'z' */ string getShortName() { - result = this.getName().suffix(this.getPackage().getName().length()+1) + result = this.getName().suffix(this.getPackage().getName().length() + 1) or result = this.getName() and not exists(this.getPackage()) } - /** Whether this module is imported by 'import name'. For example on a linux system, - * the module 'posixpath' is imported as 'os.path' or as 'posixpath' */ - predicate importedAs(string name) { - PointsToInternal::module_imported_as(theModule(), name) - } + /** + * Whether this module is imported by 'import name'. For example on a linux system, + * the module 'posixpath' is imported as 'os.path' or as 'posixpath' + */ + predicate importedAs(string name) { PointsToInternal::module_imported_as(theModule(), name) } ModuleObject getAnImportedModule() { result.importedAs(this.getModule().getAnImportedModuleName()) } - /** Gets the kind for this module. Will be one of + /** + * Gets the kind for this module. Will be one of * "module", "script" or "plugin". */ - string getKind() { - result = getKindForModule(this) - } - - override boolean booleanValue() { - result = true - } + string getKind() { result = getKindForModule(this) } + override boolean booleanValue() { result = true } } class BuiltinModuleObject extends ModuleObject { + BuiltinModuleObject() { this.asBuiltin().getClass() = theModuleType().asBuiltin() } - BuiltinModuleObject () { - this.asBuiltin().getClass() = theModuleType().asBuiltin() - } - - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } override Object getAttribute(string name) { result.asBuiltin() = this.asBuiltin().getMember(name) } - override predicate hasAttribute(string name) { - exists(this.asBuiltin().getMember(name)) - } - - override predicate exportsComplete() { - any() - } - + override predicate hasAttribute(string name) { exists(this.asBuiltin().getMember(name)) } + override predicate exportsComplete() { any() } } class PythonModuleObject extends ModuleObject { + PythonModuleObject() { exists(Module m | m.getEntryNode() = this | not m.isPackage()) } - PythonModuleObject() { - exists(Module m | m.getEntryNode() = this | - not m.isPackage() - ) - } + override string getName() { result = this.getModule().getName() } - override string getName() { - result = this.getModule().getName() - } + override Module getModule() { result = this.getOrigin() } - override Module getModule() { - result = this.getOrigin() - } + override Module getSourceModule() { result = this.getOrigin() } - override Module getSourceModule() { - result = this.getOrigin() - } - - override Container getPath() { - result = this.getModule().getFile() - } + override Container getPath() { result = this.getModule().getFile() } override predicate exportsComplete() { - exists(Module m | - m = this.getModule() | - not exists(Call modify, Attribute attr, GlobalVariable all | - modify.getScope() = m and modify.getFunc() = attr and - all.getId() = "__all__" | + exists(Module m | m = this.getModule() | + not exists(Call modify, Attribute attr, GlobalVariable all | + modify.getScope() = m and + modify.getFunc() = attr and + all.getId() = "__all__" + | attr.getObject().(Name).uses(all) ) ) } - } -/** Primarily for internal use. +/** + * Primarily for internal use. * - * Gets the object for the string text. - * The extractor will have populated a str object + * Gets the object for the string text. + * The extractor will have populated a str object * for each module name, with the name b'text' or u'text' (including the quotes). */ Object object_for_string(string text) { result.asBuiltin().getClass() = theStrType().asBuiltin() and exists(string repr | repr = result.asBuiltin().getName() and - repr.charAt(1) = "'" | + repr.charAt(1) = "'" + | /* Strip quotes off repr */ - text = repr.substring(2, repr.length()-1) + text = repr.substring(2, repr.length() - 1) ) } class PackageObject extends ModuleObject { + PackageObject() { exists(Module p | p.getEntryNode() = this | p.isPackage()) } - PackageObject() { - exists(Module p | p.getEntryNode() = this | - p.isPackage() - ) - } + override string getName() { result = this.getModule().getName() } - override string getName() { - result = this.getModule().getName() - } + override Module getModule() { result = this.getOrigin() } - override Module getModule() { - result = this.getOrigin() - } + override Module getSourceModule() { result = this.getModule().getInitModule() } - override Module getSourceModule() { - result = this.getModule().getInitModule() - } - - override Container getPath() { - result = this.getModule().getPath() - } + override Container getPath() { result = this.getModule().getPath() } ModuleObject submodule(string name) { result.getPackage() = this and @@ -235,9 +186,7 @@ class PackageObject extends ModuleObject { ) } - PythonModuleObject getInitModule() { - result.getModule() = this.getModule().getInitModule() - } + PythonModuleObject getInitModule() { result.getModule() = this.getModule().getInitModule() } /** Holds if this package has no `__init__.py` file. */ predicate hasNoInitModule() { @@ -259,23 +208,19 @@ class PackageObject extends ModuleObject { this.getInitModule().hasAttribute(name) } - Location getLocation() { - none() - } + Location getLocation() { none() } override predicate hasLocationInfo(string path, int bl, int bc, int el, int ec) { path = this.getPath().getName() and - bl = 0 and bc = 0 and el = 0 and ec = 0 + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } - } /** Utility module for predicates relevant to the `ModuleObject` class. */ module ModuleObject { - /** Gets a `ModuleObject` called `name`, if it exists. */ - ModuleObject named(string name) { - result.getName() = name - } - + ModuleObject named(string name) { result.getName() = name } } diff --git a/python/ql/src/semmle/python/types/Object.qll b/python/ql/src/semmle/python/types/Object.qll index fa6512bec5b..f015972d0b6 100644 --- a/python/ql/src/semmle/python/types/Object.qll +++ b/python/ql/src/semmle/python/types/Object.qll @@ -3,7 +3,8 @@ private import semmle.python.objects.ObjectAPI private import semmle.python.objects.ObjectInternal private import semmle.python.types.Builtins -private cached predicate is_an_object(@py_object obj) { +cached +private predicate is_an_object(@py_object obj) { /* CFG nodes for numeric literals, all of which have a @py_cobject for the value of that literal */ obj instanceof ControlFlowNode and not obj.(ControlFlowNode).getNode() instanceof IntegerLiteral and @@ -12,30 +13,30 @@ private cached predicate is_an_object(@py_object obj) { obj instanceof Builtin } -/** Instances of this class represent objects in the Python program. However, since +/** + * Instances of this class represent objects in the Python program. However, since * the QL database is static and Python programs are dynamic, there are necessarily a - * number of approximations. + * number of approximations. * * Each point in the control flow graph where a new object can be created is treated as - * an object. Many builtin objects, such as integers, strings and builtin classes, are - * also treated as 'objects'. Hence each 'object', that is an instance of this class, - * represents a set of actual Python objects in the actual program. + * an object. Many builtin objects, such as integers, strings and builtin classes, are + * also treated as 'objects'. Hence each 'object', that is an instance of this class, + * represents a set of actual Python objects in the actual program. * - * Ideally each set would contain only one member, but that is not possible in practice. - * Many instances of this class will represent many actual Python objects, especially - * if the point in the control flow graph to which they refer is in a loop. Others may not - * refer to any objects. However, for many important objects such as classes and functions, + * Ideally each set would contain only one member, but that is not possible in practice. + * Many instances of this class will represent many actual Python objects, especially + * if the point in the control flow graph to which they refer is in a loop. Others may not + * refer to any objects. However, for many important objects such as classes and functions, * there is a one-to-one relation. */ class Object extends @py_object { + Object() { is_an_object(this) } - Object() { - is_an_object(this) - } - - /** Gets an inferred type for this object, without using inter-procedural analysis. + /** + * Gets an inferred type for this object, without using inter-procedural analysis. * WARNING: The lack of context makes this less accurate than f.refersTo(this, result, _) - * for a control flow node 'f' */ + * for a control flow node 'f' + */ ClassObject getAnInferredType() { exists(ControlFlowNode somewhere | somewhere.refersTo(this, result, _)) or @@ -44,57 +45,57 @@ class Object extends @py_object { this = unknownValue() and result = theUnknownType() } - /** Whether this is a builtin object. A builtin object is one defined by the implementation, - * such as the integer 4 or by a native extension, such as a NumPy array class. */ - predicate isBuiltin() { - exists(this.asBuiltin()) - } + /** + * Whether this is a builtin object. A builtin object is one defined by the implementation, + * such as the integer 4 or by a native extension, such as a NumPy array class. + */ + predicate isBuiltin() { exists(this.asBuiltin()) } /** Retained for backwards compatibility. See Object.isBuiltin() */ - predicate isC() { - this.isBuiltin() - } + predicate isC() { this.isBuiltin() } - /** Gets the point in the source code from which this object "originates". + /** + * Gets the point in the source code from which this object "originates". * * WARNING: The lack of context makes this less accurate than f.refersTo(this, _, result) * for a control flow node 'f'. */ - AstNode getOrigin() { - py_flow_bb_node(this, result, _, _) - } + AstNode getOrigin() { py_flow_bb_node(this, result, _, _) } - private predicate hasOrigin() { - py_flow_bb_node(this, _, _, _) - } + private predicate hasOrigin() { py_flow_bb_node(this, _, _, _) } predicate hasLocationInfo(string filepath, int bl, int bc, int el, int ec) { this.hasOrigin() and this.getOrigin().getLocation().hasLocationInfo(filepath, bl, bc, el, ec) or - not this.hasOrigin() and filepath = ":Compiled Code" and bl = 0 and bc = 0 and el = 0 and ec = 0 + not this.hasOrigin() and + filepath = ":Compiled Code" and + bl = 0 and + bc = 0 and + el = 0 and + ec = 0 } /** INTERNAL -- Do not use */ - Builtin asBuiltin() { - result = this - } + Builtin asBuiltin() { result = this } string toString() { - not this = undefinedVariable() and not this = unknownValue() and - exists(ClassObject type | - type.asBuiltin() = this.asBuiltin().getClass() | + not this = undefinedVariable() and + not this = unknownValue() and + exists(ClassObject type | type.asBuiltin() = this.asBuiltin().getClass() | result = type.getName() + " " + this.asBuiltin().getName() ) or result = this.getOrigin().toString() } - /** Gets the class of this object for simple cases, namely constants, functions, + /** + * Gets the class of this object for simple cases, namely constants, functions, * comprehensions and built-in objects. * * This exists primarily for internal use. Use getAnInferredType() instead. */ - cached ClassObject simpleClass() { + cached + ClassObject simpleClass() { result = comprehension(this.getOrigin()) or result = collection_literal(this.getOrigin()) @@ -108,29 +109,23 @@ class Object extends @py_object { result.(Object).asBuiltin() = this.asBuiltin().getClass() } - private - ClassObject declaringClass(string name) { - result.declaredAttribute(name) = this - } + private ClassObject declaringClass(string name) { result.declaredAttribute(name) = this } - /** Whether this overrides o. In this context, "overrides" means that this object + /** + * Whether this overrides o. In this context, "overrides" means that this object * is a named attribute of a some class C and `o` is a named attribute of another * class S, both attributes having the same name, and S is a super class of C. */ predicate overrides(Object o) { - exists(string name | - declaringClass(name).getASuperType() = o.declaringClass(name) - ) + exists(string name | declaringClass(name).getASuperType() = o.declaringClass(name)) } private boolean booleanFromValue() { - exists(ObjectInternal obj | - obj.getSource() = this | - result = obj.booleanValue() - ) + exists(ObjectInternal obj | obj.getSource() = this | result = obj.booleanValue()) } - /** The Boolean value of this object if it always evaluates to true or false. + /** + * The Boolean value of this object if it always evaluates to true or false. * For example: * false for None, true for 7 and no result for int(x) */ @@ -144,22 +139,26 @@ class Object extends @py_object { booleanFromValue() = false } - predicate notClass() { - any() - } + predicate notClass() { any() } - /** Holds if this object can be referred to by `longName` + /** + * Holds if this object can be referred to by `longName` * For example, the modules `dict` in the `sys` module * has the long name `sys.modules` and the name `os.path.join` * will refer to the path joining function even though it might * be declared in the `posix` or `nt` modules. * Long names can have no more than three dots after the module name. */ - cached predicate hasLongName(string longName) { - this = findByName0(longName) or - this = findByName1(longName) or - this = findByName2(longName) or - this = findByName3(longName) or + cached + predicate hasLongName(string longName) { + this = findByName0(longName) + or + this = findByName1(longName) + or + this = findByName2(longName) + or + this = findByName3(longName) + or exists(ClassMethodObject cm | cm.hasLongName(longName) and cm.getFunction() = this @@ -170,64 +169,54 @@ class Object extends @py_object { cm.getFunction() = this ) } - } -private Object findByName0(string longName) { - result.(ModuleObject).getName() = longName -} +private Object findByName0(string longName) { result.(ModuleObject).getName() = longName } private Object findByName1(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName0(owner).(ModuleObject).attr(attrname) or result = findByName0(owner).(ClassObject).lookupAttribute(attrname) - ) - and + ) and not result = findByName0(_) } private Object findByName2(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName1(owner).(ModuleObject).attr(attrname) or result = findByName1(owner).(ClassObject).lookupAttribute(attrname) - ) - and not result = findByName0(_) - and not result = findByName1(_) + ) and + not result = findByName0(_) and + not result = findByName1(_) } private Object findByName3(string longName) { - exists(string owner, string attrname | - longName = owner + "." + attrname - | + exists(string owner, string attrname | longName = owner + "." + attrname | result = findByName2(owner).(ModuleObject).attr(attrname) or result = findByName2(owner).(ClassObject).lookupAttribute(attrname) - ) - and not result = findByName0(_) - and not result = findByName1(_) - and not result = findByName2(_) + ) and + not result = findByName0(_) and + not result = findByName1(_) and + not result = findByName2(_) } - -/** Numeric objects (ints and floats). +/** + * Numeric objects (ints and floats). * Includes those occurring in the source as a literal * or in a builtin module as a value. */ class NumericObject extends Object { - NumericObject() { this.asBuiltin().getClass() = theIntType().asBuiltin() or this.asBuiltin().getClass() = theLongType().asBuiltin() or this.asBuiltin().getClass() = theFloatType().asBuiltin() } - /** Gets the Boolean value that this object + /** + * Gets the Boolean value that this object * would evaluate to in a Boolean context, * such as `bool(x)` or `if x: ...` */ @@ -241,51 +230,44 @@ class NumericObject extends Object { this.floatValue() = 0 and result = false } - /** Gets the value of this object if it is a constant integer and it fits in a QL int */ + /** Gets the value of this object if it is a constant integer and it fits in a QL int */ int intValue() { ( this.asBuiltin().getClass() = theIntType().asBuiltin() or this.asBuiltin().getClass() = theLongType().asBuiltin() - ) - and + ) and result = this.asBuiltin().getName().toInt() } - /** Gets the value of this object if it is a constant float */ + /** Gets the value of this object if it is a constant float */ float floatValue() { - this.asBuiltin().getClass() = theFloatType().asBuiltin() - and + this.asBuiltin().getClass() = theFloatType().asBuiltin() and result = this.asBuiltin().getName().toFloat() } /** Gets the string representation of this object, equivalent to calling repr() in Python */ string repr() { - exists(string s | - s = this.asBuiltin().getName() | - if this.asBuiltin().getClass() = theLongType().asBuiltin() then - result = s + "L" - else - result = s + exists(string s | s = this.asBuiltin().getName() | + if this.asBuiltin().getClass() = theLongType().asBuiltin() + then result = s + "L" + else result = s ) } - } -/** String objects (unicode or bytes). +/** + * String objects (unicode or bytes). * Includes those occurring in the source as a literal * or in a builtin module as a value. */ class StringObject extends Object { - StringObject() { this.asBuiltin().getClass() = theUnicodeType().asBuiltin() or this.asBuiltin().getClass() = theBytesType().asBuiltin() } /** Whether this string is composed entirely of ascii encodable characters */ - predicate isAscii() { - this.getText().regexpMatch("^\\p{ASCII}*$") - } + predicate isAscii() { this.getText().regexpMatch("^\\p{ASCII}*$") } override boolean booleanValue() { this.getText() = "" and result = false @@ -294,22 +276,21 @@ class StringObject extends Object { } /** Gets the text for this string */ - cached string getText() { + cached + string getText() { exists(string quoted_string | - quoted_string = this.asBuiltin().getName() - and + quoted_string = this.asBuiltin().getName() and result = quoted_string.regexpCapture("[bu]'([\\s\\S]*)'", 1) ) } - } -/** Sequence objects (lists and tuples) +/** + * Sequence objects (lists and tuples) * Includes those occurring in the source as a literal * or in a builtin module as a value. */ abstract class SequenceObject extends Object { - /** Gets the length of this sequence */ int getLength() { result = strictcount(this.getBuiltinElement(_)) @@ -318,25 +299,19 @@ abstract class SequenceObject extends Object { } /** Gets the nth item of this builtin sequence */ - Object getBuiltinElement(int n) { - result.asBuiltin() = this.asBuiltin().getItem(n) - } + Object getBuiltinElement(int n) { result.asBuiltin() = this.asBuiltin().getItem(n) } /** Gets the nth source element of this sequence */ - ControlFlowNode getSourceElement(int n) { - result = this.(SequenceNode).getElement(n) - } + ControlFlowNode getSourceElement(int n) { result = this.(SequenceNode).getElement(n) } Object getInferredElement(int n) { result = this.getBuiltinElement(n) or this.getSourceElement(n).refersTo(result) } - } class TupleObject extends SequenceObject { - TupleObject() { this.asBuiltin().getClass() = theTupleType().asBuiltin() or @@ -344,118 +319,73 @@ class TupleObject extends SequenceObject { or exists(Function func | func.getVararg().getAFlowNode() = this) } - } module TupleObject { - TupleObject empty() { exists(Builtin empty | empty = result.asBuiltin() and - empty.getClass() = theTupleType().asBuiltin() and + empty.getClass() = theTupleType().asBuiltin() and not exists(empty.getItem(_)) ) } - } class NonEmptyTupleObject extends TupleObject { + NonEmptyTupleObject() { exists(Function func | func.getVararg().getAFlowNode() = this) } - NonEmptyTupleObject() { - exists(Function func | func.getVararg().getAFlowNode() = this) - } - - override boolean booleanValue() { - result = true - } - + override boolean booleanValue() { result = true } } - class ListObject extends SequenceObject { - ListObject() { this.asBuiltin().getClass() = theListType().asBuiltin() or this instanceof ListNode } - } /** The `builtin` module */ -BuiltinModuleObject theBuiltinModuleObject() { - result.asBuiltin() = Builtin::builtinModule() -} +BuiltinModuleObject theBuiltinModuleObject() { result.asBuiltin() = Builtin::builtinModule() } /** The `sys` module */ -BuiltinModuleObject theSysModuleObject() { - result.asBuiltin() = Builtin::special("sys") -} +BuiltinModuleObject theSysModuleObject() { result.asBuiltin() = Builtin::special("sys") } /** DEPRECATED -- Use `Object::builtin(name)` instead. */ -deprecated -Object builtin_object(string name) { - result = Object::builtin(name) -} +deprecated Object builtin_object(string name) { result = Object::builtin(name) } /** The built-in object None */ -Object theNoneObject() { - result.asBuiltin() = Builtin::special("None") -} +Object theNoneObject() { result.asBuiltin() = Builtin::special("None") } /** The built-in object True */ -Object theTrueObject() { - result.asBuiltin() = Builtin::special("True") -} +Object theTrueObject() { result.asBuiltin() = Builtin::special("True") } /** The built-in object False */ -Object theFalseObject() { - result.asBuiltin() = Builtin::special("False") -} +Object theFalseObject() { result.asBuiltin() = Builtin::special("False") } /** The NameError class */ -Object theNameErrorType() { - result = Object::builtin("NameError") -} +Object theNameErrorType() { result = Object::builtin("NameError") } /** The StandardError class */ -Object theStandardErrorType() { - result = Object::builtin("StandardError") -} +Object theStandardErrorType() { result = Object::builtin("StandardError") } /** The IndexError class */ -Object theIndexErrorType() { - result = Object::builtin("IndexError") -} +Object theIndexErrorType() { result = Object::builtin("IndexError") } /** The LookupError class */ -Object theLookupErrorType() { - result = Object::builtin("LookupError") -} +Object theLookupErrorType() { result = Object::builtin("LookupError") } /** DEPRECATED -- Use `Object::quitter(name)` instead. */ -deprecated -Object quitterObject(string name) { - result = Object::quitter(name) -} +deprecated Object quitterObject(string name) { result = Object::quitter(name) } /** DEPRECATED -- Use `Object::notImplemented()` instead. */ -deprecated -Object theNotImplementedObject() { - result = Object::builtin("NotImplemented") -} +deprecated Object theNotImplementedObject() { result = Object::builtin("NotImplemented") } /** DEPRECATED -- Use `TupleObject::empty()` instead. */ -deprecated -Object theEmptyTupleObject() { - result = TupleObject::empty() -} +deprecated Object theEmptyTupleObject() { result = TupleObject::empty() } module Object { - - Object builtin(string name) { - result.asBuiltin() = Builtin::builtin(name) - } + Object builtin(string name) { result.asBuiltin() = Builtin::builtin(name) } /** The named quitter object (quit or exit) in the builtin namespace */ Object quitter(string name) { @@ -464,13 +394,9 @@ module Object { } /** The builtin object `NotImplemented`. Not be confused with `NotImplementedError`. */ - Object notImplemented() { - result = builtin("NotImplemented") - } - + Object notImplemented() { result = builtin("NotImplemented") } } - private ClassObject comprehension(Expr e) { e instanceof ListComp and result = theListType() or @@ -497,23 +423,17 @@ private ClassObject string_literal(Expr e) { e instanceof Unicode and result = theUnicodeType() } -Object theUnknownType() { - result.asBuiltin() = Builtin::unknownType() -} +Object theUnknownType() { result.asBuiltin() = Builtin::unknownType() } /* For backwards compatibility */ - class SuperBoundMethod extends Object { - string name; SuperBoundMethod() { this.(AttrNode).getObject(name).inferredValue().getClass() = Value::named("super") } - override string toString() { - result = "super()." + name - } + override string toString() { result = "super()." + name } Object getFunction(string fname) { fname = name and @@ -523,7 +443,4 @@ class SuperBoundMethod extends Object { result = m.getFunction().getSource() ) } - } - - diff --git a/python/ql/src/semmle/python/types/Properties.qll b/python/ql/src/semmle/python/types/Properties.qll index b0b14262590..207562c63c6 100644 --- a/python/ql/src/semmle/python/types/Properties.qll +++ b/python/ql/src/semmle/python/types/Properties.qll @@ -1,14 +1,14 @@ import python -/** A Python property: - * @property - * def f(): +/** + * A Python property: + * + * @property def f(): * .... * * Also any instances of types.GetSetDescriptorType (which are equivalent, but implemented in C) */ abstract class PropertyObject extends Object { - PropertyObject() { property_getter(this, _) or @@ -27,118 +27,82 @@ abstract class PropertyObject extends Object { /** Gets the deleter of this property */ abstract Object getDeleter(); - override string toString() { - result = "Property " + this.getName() - } + override string toString() { result = "Property " + this.getName() } /** Whether this property is read-only. */ - predicate isReadOnly() { - not exists(this.getSetter()) - } + predicate isReadOnly() { not exists(this.getSetter()) } - /** Gets an inferred type of this property. + /** + * Gets an inferred type of this property. * That is the type returned by its getter function, - * not the type of the property object which is types.PropertyType. */ + * not the type of the property object which is types.PropertyType. + */ abstract ClassObject getInferredPropertyType(); - } - class PythonPropertyObject extends PropertyObject { + PythonPropertyObject() { property_getter(this, _) } - PythonPropertyObject() { - property_getter(this, _) - } - - override string getName() { - result = this.getGetter().getName() - } + override string getName() { result = this.getGetter().getName() } /** Gets the getter function of this property */ - override FunctionObject getGetter() { - property_getter(this, result) - } + override FunctionObject getGetter() { property_getter(this, result) } override ClassObject getInferredPropertyType() { result = this.getGetter().getAnInferredReturnType() } /** Gets the setter function of this property */ - override FunctionObject getSetter() { - property_setter(this, result) - } + override FunctionObject getSetter() { property_setter(this, result) } /** Gets the deleter function of this property */ - override FunctionObject getDeleter() { - property_deleter(this, result) - } - + override FunctionObject getDeleter() { property_deleter(this, result) } } class BuiltinPropertyObject extends PropertyObject { + BuiltinPropertyObject() { this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin() } - BuiltinPropertyObject() { - this.asBuiltin().getClass() = theBuiltinPropertyType().asBuiltin() - } - - override string getName() { - result = this.asBuiltin().getName() - } + override string getName() { result = this.asBuiltin().getName() } /** Gets the getter method wrapper of this property */ - override Object getGetter() { - result.asBuiltin() = this.asBuiltin().getMember("__get__") - } + override Object getGetter() { result.asBuiltin() = this.asBuiltin().getMember("__get__") } - override ClassObject getInferredPropertyType() { - none() - } + override ClassObject getInferredPropertyType() { none() } /** Gets the setter method wrapper of this property */ - override Object getSetter() { - result.asBuiltin() = this.asBuiltin().getMember("__set__") - } + override Object getSetter() { result.asBuiltin() = this.asBuiltin().getMember("__set__") } /** Gets the deleter method wrapper of this property */ - override Object getDeleter() { - result.asBuiltin() = this.asBuiltin().getMember("__delete__") - } - + override Object getDeleter() { result.asBuiltin() = this.asBuiltin().getMember("__delete__") } } private predicate property_getter(CallNode decorated, FunctionObject getter) { - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(0).refersTo(getter) } private predicate property_setter(CallNode decorated, FunctionObject setter) { - property_getter(decorated, _) - and + property_getter(decorated, _) and exists(CallNode setter_call, AttrNode prop_setter | - prop_setter.getObject("setter").refersTo((Object)decorated) | - setter_call.getArg(0).refersTo(setter) - and + prop_setter.getObject("setter").refersTo(decorated.(Object)) + | + setter_call.getArg(0).refersTo(setter) and setter_call.getFunction() = prop_setter ) or - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(1).refersTo(setter) } private predicate property_deleter(CallNode decorated, FunctionObject deleter) { - property_getter(decorated, _) - and + property_getter(decorated, _) and exists(CallNode deleter_call, AttrNode prop_deleter | - prop_deleter.getObject("deleter").refersTo((Object)decorated) | - deleter_call.getArg(0).refersTo(deleter) - and + prop_deleter.getObject("deleter").refersTo(decorated.(Object)) + | + deleter_call.getArg(0).refersTo(deleter) and deleter_call.getFunction() = prop_deleter ) or - decorated.getFunction().refersTo(thePropertyType()) - and + decorated.getFunction().refersTo(thePropertyType()) and decorated.getArg(2).refersTo(deleter) } - diff --git a/python/ql/src/semmle/python/types/Version.qll b/python/ql/src/semmle/python/types/Version.qll index c55f0ea459c..26ab46e970a 100644 --- a/python/ql/src/semmle/python/types/Version.qll +++ b/python/ql/src/semmle/python/types/Version.qll @@ -1,18 +1,16 @@ import python -/** A Version of the Python interpreter. - * Currently only 2.7 or 3.x but may include different sets of versions in the future. */ +/** + * A Version of the Python interpreter. + * Currently only 2.7 or 3.x but may include different sets of versions in the future. + */ class Version extends int { - - Version() { - this = 2 or this = 3 - } + Version() { this = 2 or this = 3 } /** Holds if this version (or set of versions) includes the version `major`.`minor` */ predicate includes(int major, int minor) { this = 2 and major = 2 and minor = 7 or - this = 3 and major = 3 and minor in [4..8] + this = 3 and major = 3 and minor in [4 .. 8] } - } diff --git a/python/ql/src/semmle/python/values/StringAttributes.qll b/python/ql/src/semmle/python/values/StringAttributes.qll index 248a11f6ae2..1209313eaf1 100644 --- a/python/ql/src/semmle/python/values/StringAttributes.qll +++ b/python/ql/src/semmle/python/values/StringAttributes.qll @@ -1,10 +1,12 @@ import python predicate string_attribute_all(ControlFlowNode n, string attr) { - (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and attr = "const" + (n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and + attr = "const" or exists(Object s | - n.refersTo(s, theBytesType(), _) and attr = "bytes" and + n.refersTo(s, theBytesType(), _) and + attr = "bytes" and // We are only interested in bytes if they may cause an exception if // implicitly converted to unicode. ASCII is safe. not s.(StringObject).isAscii() @@ -12,23 +14,19 @@ predicate string_attribute_all(ControlFlowNode n, string attr) { } predicate tracked_object(ControlFlowNode obj, string attr) { - tracked_object_all(obj, attr) - or - tracked_object_any(obj, attr) + tracked_object_all(obj, attr) + or + tracked_object_any(obj, attr) } -predicate open_file(Object obj) { - obj.(CallNode).getFunction().refersTo(Object::builtin("open")) -} +predicate open_file(Object obj) { obj.(CallNode).getFunction().refersTo(Object::builtin("open")) } predicate string_attribute_any(ControlFlowNode n, string attr) { attr = "user-input" and - exists(Object input | - n.(CallNode).getFunction().refersTo(input) | - if major_version() = 2 then - input = Object::builtin("raw_input") - else - input = Object::builtin("input") + exists(Object input | n.(CallNode).getFunction().refersTo(input) | + if major_version() = 2 + then input = Object::builtin("raw_input") + else input = Object::builtin("input") ) or attr = "file-input" and @@ -42,19 +40,13 @@ predicate string_attribute_any(ControlFlowNode n, string attr) { predicate tracked_object_any(ControlFlowNode obj, string attr) { string_attribute_any(obj, attr) or - exists(ControlFlowNode other | - tracking_step(other, obj) | - tracked_object_any(other, attr) - ) + exists(ControlFlowNode other | tracking_step(other, obj) | tracked_object_any(other, attr)) } predicate tracked_object_all(ControlFlowNode obj, string attr) { string_attribute_all(obj, attr) or - forex(ControlFlowNode other | - tracking_step(other, obj) | - tracked_object_all(other, attr) - ) + forex(ControlFlowNode other | tracking_step(other, obj) | tracked_object_all(other, attr)) } predicate tracked_call_step(ControlFlowNode ret, ControlFlowNode call) { @@ -72,7 +64,7 @@ ControlFlowNode sequence_for_iterator(ControlFlowNode f) { ) } -pragma [noinline] +pragma[noinline] private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) { src = dest.(BinaryExprNode).getAnOperand() or @@ -86,5 +78,5 @@ private predicate tracking_step(ControlFlowNode src, ControlFlowNode dest) { or tracked_call_step(src, dest) or - dest.refersTo((Object)src) + dest.refersTo(src.(Object)) } diff --git a/python/ql/src/semmle/python/web/Http.qll b/python/ql/src/semmle/python/web/Http.qll index e12cb6abe96..566d2e11fc4 100644 --- a/python/ql/src/semmle/python/web/Http.qll +++ b/python/ql/src/semmle/python/web/Http.qll @@ -4,15 +4,13 @@ import semmle.python.security.strings.External import HttpConstants /** Generic taint source from a http request */ -abstract class HttpRequestTaintSource extends TaintSource { +abstract class HttpRequestTaintSource extends TaintSource { } -} - -/** Taint kind representing the WSGI environment. +/** + * Taint kind representing the WSGI environment. * As specified in PEP 3333. https://www.python.org/dev/peps/pep-3333/#environ-variables */ class WsgiEnvironment extends TaintKind { - WsgiEnvironment() { this = "wsgi.environment" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { @@ -26,10 +24,12 @@ class WsgiEnvironment extends TaintKind { tonode.(CallNode).getFunction().(AttrNode).getObject("get") = fromnode and tonode.(CallNode).getArg(0).pointsTo(key) or - tonode.(SubscriptNode).getObject() = fromnode and tonode.isLoad() and + tonode.(SubscriptNode).getObject() = fromnode and + tonode.isLoad() and tonode.(SubscriptNode).getIndex().pointsTo(key) - | - key = Value::forString(text) and result instanceof ExternalStringKind and + | + key = Value::forString(text) and + result instanceof ExternalStringKind and ( text = "QUERY_STRING" or text = "PATH_INFO" or @@ -37,96 +37,73 @@ class WsgiEnvironment extends TaintKind { ) ) } - } -/** A standard morsel object from a HTTP request, a value in a cookie, - * typically an instance of `http.cookies.Morsel` */ +/** + * A standard morsel object from a HTTP request, a value in a cookie, + * typically an instance of `http.cookies.Morsel` + */ class UntrustedMorsel extends TaintKind { - - UntrustedMorsel() { - this = "http.Morsel" - } - + UntrustedMorsel() { this = "http.Morsel" } override TaintKind getTaintOfAttribute(string name) { result instanceof ExternalStringKind and - ( - name = "value" - ) + name = "value" } - } /** A standard cookie object from a HTTP request, typically an instance of `http.cookies.SimpleCookie` */ class UntrustedCookie extends TaintKind { - - UntrustedCookie() { - this = "http.Cookie" - } + UntrustedCookie() { this = "http.Cookie" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(SubscriptNode).getObject() = fromnode and result instanceof UntrustedMorsel } - } abstract class CookieOperation extends @py_flow_node { - abstract string toString(); abstract ControlFlowNode getKey(); abstract ControlFlowNode getValue(); - } -abstract class CookieGet extends CookieOperation {} +abstract class CookieGet extends CookieOperation { } -abstract class CookieSet extends CookieOperation {} +abstract class CookieSet extends CookieOperation { } /** Generic taint sink in a http response */ abstract class HttpResponseTaintSink extends TaintSink { - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } abstract class HttpRedirectTaintSink extends TaintSink { - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } module Client { - // TODO: user-input in other than URL: // - `data`, `json` for `requests.post` // - `body` for `HTTPConnection.request` // - headers? - // TODO: Add more library support // - urllib3 https://github.com/urllib3/urllib3 // - httpx https://github.com/encode/httpx - /** - * An outgoing http request - * - * For example: - * conn = HTTPConnection('example.com') - conn.request('GET', '/path') - */ + * An outgoing http request + * + * For example: + * conn = HTTPConnection('example.com') + * conn.request('GET', '/path') + */ abstract class HttpRequest extends ControlFlowNode { - - /** Get any ControlFlowNode that is used to construct the final URL. - * - * In the HTTPConnection example, there is a result for both `'example.com'` and for `'/path'`. - */ + /** + * Get any ControlFlowNode that is used to construct the final URL. + * + * In the HTTPConnection example, there is a result for both `'example.com'` and for `'/path'`. + */ abstract ControlFlowNode getAUrlPart(); abstract string getMethodUpper(); @@ -134,14 +111,8 @@ module Client { /** Taint sink for the URL-part of an outgoing http request */ class HttpRequestUrlTaintSink extends TaintSink { + HttpRequestUrlTaintSink() { this = any(HttpRequest r).getAUrlPart() } - HttpRequestUrlTaintSink() { - this = any(HttpRequest r).getAUrlPart() - } - - override predicate sinks(TaintKind kind) { - kind instanceof ExternalStringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } } } diff --git a/python/ql/src/semmle/python/web/HttpConstants.qll b/python/ql/src/semmle/python/web/HttpConstants.qll index a20b89f9f63..41f3905b887 100644 --- a/python/ql/src/semmle/python/web/HttpConstants.qll +++ b/python/ql/src/semmle/python/web/HttpConstants.qll @@ -1,13 +1,13 @@ - /** Gets an http verb */ string httpVerb() { - result = "GET" or result = "POST" or - result = "PUT" or result = "PATCH" or - result = "DELETE" or result = "OPTIONS" or + result = "GET" or + result = "POST" or + result = "PUT" or + result = "PATCH" or + result = "DELETE" or + result = "OPTIONS" or result = "HEAD" } /** Gets an http verb, in lower case */ -string httpVerbLower() { - result = httpVerb().toLowerCase() -} +string httpVerbLower() { result = httpVerb().toLowerCase() } diff --git a/python/ql/src/semmle/python/web/HttpRedirect.qll b/python/ql/src/semmle/python/web/HttpRedirect.qll index e77f0841195..cfbe35f30f1 100644 --- a/python/ql/src/semmle/python/web/HttpRedirect.qll +++ b/python/ql/src/semmle/python/web/HttpRedirect.qll @@ -1,7 +1,5 @@ import python - import semmle.python.security.strings.Basic - import semmle.python.web.django.Redirect import semmle.python.web.flask.Redirect import semmle.python.web.tornado.Redirect diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll index f2cc54f49b6..8d707a3a6e6 100644 --- a/python/ql/src/semmle/python/web/django/General.qll +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -27,11 +27,8 @@ abstract class DjangoRoute extends CallNode { * https://docs.djangoproject.com/en/3.0/topics/http/views/ */ class DjangoViewHandler extends PythonFunctionValue { - /** Gets the index of the 'request' argument */ - int getRequestArgIndex() { - result = 0 - } + int getRequestArgIndex() { result = 0 } } /** @@ -48,11 +45,7 @@ private class DjangoViewClass extends ClassValue { } class DjangoClassBasedViewHandler extends DjangoViewHandler { - DjangoClassBasedViewHandler() { - exists(DjangoViewClass cls | - cls.lookup(httpVerbLower()) = this - ) - } + DjangoClassBasedViewHandler() { exists(DjangoViewClass cls | cls.lookup(httpVerbLower()) = this) } override int getRequestArgIndex() { // due to `self` being the first parameter diff --git a/python/ql/src/semmle/python/web/django/Redirect.qll b/python/ql/src/semmle/python/web/django/Redirect.qll index cc63f678973..a550088eaf6 100644 --- a/python/ql/src/semmle/python/web/django/Redirect.qll +++ b/python/ql/src/semmle/python/web/django/Redirect.qll @@ -16,7 +16,5 @@ private import semmle.python.web.Http class DjangoRedirect extends HttpRedirectTaintSink { override string toString() { result = "django.redirect" } - DjangoRedirect() { - this = redirect().getACall().getAnArg() - } + DjangoRedirect() { this = redirect().getACall().getAnArg() } } diff --git a/python/ql/src/semmle/python/web/falcon/General.qll b/python/ql/src/semmle/python/web/falcon/General.qll index 4c0b347ba38..bee0ad746f6 100644 --- a/python/ql/src/semmle/python/web/falcon/General.qll +++ b/python/ql/src/semmle/python/web/falcon/General.qll @@ -6,7 +6,8 @@ ClassValue theFalconAPIClass() { result = Value::named("falcon.API") } /** Holds if `route` is routed to `resource` */ private predicate api_route(CallNode route_call, ControlFlowNode route, ClassValue resource) { - route_call.getFunction().(AttrNode).getObject("add_route").pointsTo().getClass() = theFalconAPIClass() and + route_call.getFunction().(AttrNode).getObject("add_route").pointsTo().getClass() = + theFalconAPIClass() and route_call.getArg(0) = route and route_call.getArg(1).pointsTo().getClass() = resource } diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/src/semmle/python/web/tornado/Tornado.qll index bf2e0260428..10a5c5be962 100644 --- a/python/ql/src/semmle/python/web/tornado/Tornado.qll +++ b/python/ql/src/semmle/python/web/tornado/Tornado.qll @@ -18,11 +18,11 @@ predicate isTornadoRequestHandlerInstance(ControlFlowNode node) { node.pointsTo().getClass() = aTornadoRequestHandlerClass() or /* - * In some cases, the points-to analysis won't capture all instances we care - * about. For these, we use the following syntactic check. First, that - * `node` appears inside a method of a subclass of - * `tornado.web.RequestHandler`: - */ + * In some cases, the points-to analysis won't capture all instances we care + * about. For these, we use the following syntactic check. First, that + * `node` appears inside a method of a subclass of + * `tornado.web.RequestHandler`: + */ node.getScope().getEnclosingScope() = aTornadoRequestHandlerClass().getScope() and /* Secondly, that `node` refers to the `self` argument: */ diff --git a/python/ql/src/semmle/python/web/webob/Request.qll b/python/ql/src/semmle/python/web/webob/Request.qll index 1662313e0b9..70fa311f6b0 100644 --- a/python/ql/src/semmle/python/web/webob/Request.qll +++ b/python/ql/src/semmle/python/web/webob/Request.qll @@ -1,10 +1,8 @@ import python - import semmle.python.security.TaintTracking import semmle.python.web.Http abstract class BaseWebobRequest extends TaintKind { - bindingset[this] BaseWebobRequest() { any() } @@ -17,9 +15,7 @@ abstract class BaseWebobRequest extends TaintKind { ) or result instanceof ExternalStringKind and - ( - name = "body" - ) + name = "body" } override TaintKind getTaintOfMethodResult(string name) { @@ -30,22 +26,13 @@ abstract class BaseWebobRequest extends TaintKind { name = "copy_body" ) or - result instanceof ExternalStringKind and - ( - name = "as_bytes" - ) + result instanceof ExternalStringKind and + name = "as_bytes" } - } class WebobRequest extends BaseWebobRequest { + WebobRequest() { this = "webob.Request" } - WebobRequest() { - this = "webob.Request" - } - - override ClassValue getType() { - result = Value::named("webob.request.Request") - } - + override ClassValue getType() { result = Value::named("webob.request.Request") } } diff --git a/python/ql/src/site.qll b/python/ql/src/site.qll index 3a301497828..a09d9ad8a76 100644 --- a/python/ql/src/site.qll +++ b/python/ql/src/site.qll @@ -1,7 +1,7 @@ -/** Site library - * + +/* + * Site library + * * Include predicates and classes here, if they are required to customize all analysis. - * */ - diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql index f5279480573..620944de5b9 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,5 @@ - import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql index 6fe92327f62..56498054f51 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,5 +1,4 @@ - import python from RaisingNode r -select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql index d23a5efe2f4..80831a9ca54 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,7 +1,7 @@ - import python from ControlFlowNode r, ControlFlowNode s -where s = r.getAnExceptionalSuccessor() and -not r.(RaisingNode).unlikelySuccessor(s) -select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +where + s = r.getAnExceptionalSuccessor() and + not r.(RaisingNode).unlikelySuccessor(s) +select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql index d8db11d9f1b..29bad86bf0f 100644 --- a/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/2/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,6 +1,5 @@ - import python from RaisingNode r where r.raisesUnknownType() -select r.getLocation().getStartLine(), r.toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString() diff --git a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql index a10b6bef24a..94a1db9b83d 100644 --- a/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql +++ b/python/ql/test/2/library-tests/PointsTo/import_time/Pruned.ql @@ -1,11 +1,12 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext from ControlFlowNode f, Location l, Context c - -where not PointsToInternal::reachableBlock(f.getBasicBlock(), c) and c.isImport() and -(f.getNode() instanceof FunctionExpr or f.getNode() instanceof ClassExpr) and -l = f.getLocation() and l.getFile().getShortName() = "test.py" +where + not PointsToInternal::reachableBlock(f.getBasicBlock(), c) and + c.isImport() and + (f.getNode() instanceof FunctionExpr or f.getNode() instanceof ClassExpr) and + l = f.getLocation() and + l.getFile().getShortName() = "test.py" select l.getStartLine() diff --git a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql index 25097057d07..44a35b27b27 100644 --- a/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/2/library-tests/PointsTo/imports/Runtime.ql @@ -1,9 +1,10 @@ - import python from int line, ControlFlowNode f, Object o, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, orig) and line = f.getLocation().getStartLine() and line != 0 and - not o instanceof NumericObject // Omit sys.hexversion as it will change between machines +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, orig) and + line = f.getLocation().getStartLine() and + line != 0 and + not o instanceof NumericObject // Omit sys.hexversion as it will change between machines select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), orig.toString() diff --git a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql index b658eb84474..68eec976105 100644 --- a/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/2/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,3 @@ - import python from ClassObject cls diff --git a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql index 70ef57c16c2..6cd800ac399 100644 --- a/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql +++ b/python/ql/test/2/library-tests/PointsTo/origin_uniqueness/Origin.ql @@ -1,14 +1,11 @@ import python -string short_loc(Location l) { - result = l.getFile().getShortName() + ":" + l.getStartLine() -} +string short_loc(Location l) { result = l.getFile().getShortName() + ":" + l.getStartLine() } from ControlFlowNode use, Object obj, ControlFlowNode orig, int line - -where use.refersTo(obj, orig) and -use.getLocation().getFile().getShortName() = "test.py" and -line = use.getLocation().getStartLine() and -not line = 0 - +where + use.refersTo(obj, orig) and + use.getLocation().getFile().getShortName() = "test.py" and + line = use.getLocation().getStartLine() and + not line = 0 select line, use.toString(), obj.toString(), short_loc(orig.getLocation()) diff --git a/python/ql/test/2/library-tests/classes/attr/class_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/2/library-tests/classes/attr/list_attr.ql b/python/ql/test/2/library-tests/classes/attr/list_attr.ql index 2977030252a..aad2d9489c3 100644 --- a/python/ql/test/2/library-tests/classes/attr/list_attr.ql +++ b/python/ql/test/2/library-tests/classes/attr/list_attr.ql @@ -7,10 +7,10 @@ import python from ClassObject cls, string name, Object what -where -(cls.getName() = "list" or - cls.getASuperType().getName() = "list" -) -and -cls.lookupAttribute(name) = what +where + ( + cls.getName() = "list" or + cls.getASuperType().getName() = "list" + ) and + cls.lookupAttribute(name) = what select cls.toString(), name, what.toString() diff --git a/python/ql/test/2/library-tests/classes/mro/C3.ql b/python/ql/test/2/library-tests/classes/mro/C3.ql index d04f49af51c..c4b0dd896d6 100644 --- a/python/ql/test/2/library-tests/classes/mro/C3.ql +++ b/python/ql/test/2/library-tests/classes/mro/C3.ql @@ -1,18 +1,12 @@ - import python import semmle.python.pointsto.MRO import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal ClassList mro(ClassObjectInternal cls) { - if Types::isNewStyle(cls) then - result = Mro::newStyleMro(cls) - else - result = Mro::oldStyleMro(cls) + if Types::isNewStyle(cls) then result = Mro::newStyleMro(cls) else result = Mro::oldStyleMro(cls) } from ClassObjectInternal cls where not cls.isBuiltin() - select cls.toString(), mro(cls) - diff --git a/python/ql/test/2/library-tests/classes/mro/mro.ql b/python/ql/test/2/library-tests/classes/mro/mro.ql index 0695e6ce5b8..122d31c4a9b 100644 --- a/python/ql/test/2/library-tests/classes/mro/mro.ql +++ b/python/ql/test/2/library-tests/classes/mro/mro.ql @@ -1,8 +1,7 @@ - - import python from ClassObject cls, ClassObject l, ClassObject r -where not cls.isC() and -r = cls.nextInMro(l) +where + not cls.isC() and + r = cls.nextInMro(l) select cls.toString(), l.toString(), r.toString() diff --git a/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql b/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql index 29dc596401c..475505620f4 100644 --- a/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql +++ b/python/ql/test/2/library-tests/comprehensions/SanityCheck.ql @@ -4,4 +4,6 @@ import python - select count(Comprehension c | count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode())) +select count(Comprehension c | + count(c.toString()) != 1 or count(c.getLocation()) != 1 or not exists(c.getAFlowNode()) + ) diff --git a/python/ql/test/2/library-tests/locations/general/AllLocations.ql b/python/ql/test/2/library-tests/locations/general/AllLocations.ql index 981d4560d87..9e6fcb00a05 100644 --- a/python/ql/test/2/library-tests/locations/general/AllLocations.ql +++ b/python/ql/test/2/library-tests/locations/general/AllLocations.ql @@ -9,8 +9,7 @@ import python from string classname where -exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) -or -exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) - + exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) + or + exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) select classname diff --git a/python/ql/test/2/library-tests/locations/general/Locations.ql b/python/ql/test/2/library-tests/locations/general/Locations.ql index 874eecbdb9f..b2e7f4b164d 100644 --- a/python/ql/test/2/library-tests/locations/general/Locations.ql +++ b/python/ql/test/2/library-tests/locations/general/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/2/library-tests/locations/general/Prefix.ql b/python/ql/test/2/library-tests/locations/general/Prefix.ql index ad608f84cc2..bee9e555cc6 100644 --- a/python/ql/test/2/library-tests/locations/general/Prefix.ql +++ b/python/ql/test/2/library-tests/locations/general/Prefix.ql @@ -1,5 +1,4 @@ import python - -from StrConst s -select s.getLocation().getStartLine(), s.getText(), s.getPrefix() \ No newline at end of file +from StrConst s +select s.getLocation().getStartLine(), s.getText(), s.getPrefix() diff --git a/python/ql/test/2/library-tests/locations/keywords/Locations.ql b/python/ql/test/2/library-tests/locations/keywords/Locations.ql index b638ea81e14..afe685d0864 100644 --- a/python/ql/test/2/library-tests/locations/keywords/Locations.ql +++ b/python/ql/test/2/library-tests/locations/keywords/Locations.ql @@ -1,6 +1,5 @@ import python - from Keyword k, Location l where k.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/2/library-tests/locations/strings/test.ql b/python/ql/test/2/library-tests/locations/strings/test.ql index 4a23a61d0da..be3052d9500 100644 --- a/python/ql/test/2/library-tests/locations/strings/test.ql +++ b/python/ql/test/2/library-tests/locations/strings/test.ql @@ -2,4 +2,4 @@ import python from StrConst s, int bl, int bc, int el, int ec where s.getLocation().hasLocationInfo(_, bl, bc, el, ec) -select bl, bc, el, ec, s.getText() \ No newline at end of file +select bl, bc, el, ec, s.getText() diff --git a/python/ql/test/2/library-tests/modules/general/import_test.ql b/python/ql/test/2/library-tests/modules/general/import_test.ql index 026dcf2c690..94f8c1447ca 100644 --- a/python/ql/test/2/library-tests/modules/general/import_test.ql +++ b/python/ql/test/2/library-tests/modules/general/import_test.ql @@ -1,7 +1,9 @@ import python from ImportExpr ie, string m, string t, string r -where m = ie.getImportedModuleName() and -(if ie.isTop() then t = "top" else t = "bottom") and -(if ie.isRelative() then r= "relative" else r = "absolute") -select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, r, m +where + m = ie.getImportedModuleName() and + (if ie.isTop() then t = "top" else t = "bottom") and + (if ie.isRelative() then r = "relative" else r = "absolute") +select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, + r, m diff --git a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql index e3fde98513f..50f79a57aed 100644 --- a/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/2/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,3 @@ - import python from ModuleObject m, string name diff --git a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql index 9109fcb98a8..50ded7b4124 100644 --- a/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql +++ b/python/ql/test/2/library-tests/modules/package_members/module_import_as.ql @@ -2,4 +2,4 @@ import python from ModuleObject m, string name where not m.isC() and m.importedAs(name) -select m.toString(), name \ No newline at end of file +select m.toString(), name diff --git a/python/ql/test/2/library-tests/objects/Literals.ql b/python/ql/test/2/library-tests/objects/Literals.ql index f83f4e722da..ad6e1181cfd 100644 --- a/python/ql/test/2/library-tests/objects/Literals.ql +++ b/python/ql/test/2/library-tests/objects/Literals.ql @@ -1,8 +1,6 @@ - /* Test that there are no literals that do not have a corresponding object. */ import python - string repr(Expr e) { result = e.(Num).getN() or result = e.(Bytes).getS() or @@ -10,7 +8,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where -not exists(l.getLiteralObject()) - -select l.getLocation().getStartLine(), repr(l) \ No newline at end of file +where not exists(l.getLiteralObject()) +select l.getLocation().getStartLine(), repr(l) diff --git a/python/ql/test/2/library-tests/types/classes/mro_test.ql b/python/ql/test/2/library-tests/types/classes/mro_test.ql index 181c8205289..fa2ac44d4d2 100644 --- a/python/ql/test/2/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/2/library-tests/types/classes/mro_test.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls where not cls.isC() select cls.toString(), cls.getMro() - diff --git a/python/ql/test/2/library-tests/types/classes/new_style.ql b/python/ql/test/2/library-tests/types/classes/new_style.ql index 5c66eff3e60..a0cd38b9e62 100644 --- a/python/ql/test/2/library-tests/types/classes/new_style.ql +++ b/python/ql/test/2/library-tests/types/classes/new_style.ql @@ -1,13 +1,8 @@ - import python from ClassObject cls, string style -where not cls.isC() and -not cls.failedInference() and -( - if cls.isNewStyle() then - style = "new" - else - style = "old" -) +where + not cls.isC() and + not cls.failedInference() and + (if cls.isNewStyle() then style = "new" else style = "old") select cls.toString(), style diff --git a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql index 33c6b003b99..8e4c47a3e74 100644 --- a/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/ExitRaises.ql @@ -2,5 +2,4 @@ import python from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit(s, cls) - select r.getLocation().getStartLine(), r.toString(), s.toString(), cls.toString() diff --git a/python/ql/test/2/library-tests/types/exceptions/Raises.ql b/python/ql/test/2/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/2/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/2/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/2/library-tests/types/functions/Calls.ql b/python/ql/test/2/library-tests/types/functions/Calls.ql index 87ee8a1f9d2..6fc188753e5 100644 --- a/python/ql/test/2/library-tests/types/functions/Calls.ql +++ b/python/ql/test/2/library-tests/types/functions/Calls.ql @@ -1,4 +1,3 @@ - import python from FunctionObject func, ControlFlowNode call diff --git a/python/ql/test/2/library-tests/types/functions/Never.ql b/python/ql/test/2/library-tests/types/functions/Never.ql index 3dcf47ffd4d..1e43ead7dce 100644 --- a/python/ql/test/2/library-tests/types/functions/Never.ql +++ b/python/ql/test/2/library-tests/types/functions/Never.ql @@ -2,4 +2,4 @@ import python from FunctionObject func where func.neverReturns() -select func.getOrigin().getLocation().getStartLine(), func.getName() \ No newline at end of file +select func.getOrigin().getLocation().getStartLine(), func.getName() diff --git a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql index a200a947ab0..beb955e1188 100644 --- a/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/2/library-tests/types/functions/ReturnTypes.ql @@ -1,7 +1,5 @@ - import python from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type - select func.getOrigin().getLocation().getStartLine(), func.getName(), ret_type.toString() diff --git a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql index 7fd60f2e058..6ff0563e787 100644 --- a/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/2/library-tests/types/properties/BuiltinProperties.ql @@ -1,7 +1,8 @@ import python from ClassObject cls, string name, BuiltinPropertyObject p -where cls.declaredAttribute(name) = p and -(cls = theObjectType() or cls = theListType() or cls = theTypeType()) - -select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), p.getDeleter().toString() +where + cls.declaredAttribute(name) = p and + (cls = theObjectType() or cls = theListType() or cls = theTypeType()) +select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), + p.getDeleter().toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql index f5279480573..620944de5b9 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Handles.ql @@ -1,6 +1,5 @@ - import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql index 6fe92327f62..56498054f51 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Known.ql @@ -1,5 +1,4 @@ - import python from RaisingNode r -select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString(), r.getARaisedType().toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql index d23a5efe2f4..80831a9ca54 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Likely.ql @@ -1,7 +1,7 @@ - import python from ControlFlowNode r, ControlFlowNode s -where s = r.getAnExceptionalSuccessor() and -not r.(RaisingNode).unlikelySuccessor(s) -select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +where + s = r.getAnExceptionalSuccessor() and + not r.(RaisingNode).unlikelySuccessor(s) +select r.getLocation().getStartLine(), r.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql index d8db11d9f1b..29bad86bf0f 100644 --- a/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql +++ b/python/ql/test/3/library-tests/ControlFlow/Exceptions/Unknown.ql @@ -1,6 +1,5 @@ - import python from RaisingNode r where r.raisesUnknownType() -select r.getLocation().getStartLine(), r.toString() \ No newline at end of file +select r.getLocation().getStartLine(), r.toString() diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql index 575d347fc10..cc191d7c7d8 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/Test.ql @@ -1,7 +1,5 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - where f.refersTo(o, x) - select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql index 47b1cbc5434..0c6149c38b1 100644 --- a/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql +++ b/python/ql/test/3/library-tests/PointsTo/attributes/TestWithType.ql @@ -1,7 +1,6 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - where f.refersTo(o, c, x) - -select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), + x.getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected index 3395885a548..4c45f134a93 100644 --- a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected +++ b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.expected @@ -1,5 +1,5 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:8,5-24) -WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:11,5-24) +WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:6,25-44) +WARNING: Predicate points_to has been deprecated and may be removed in future (BooleanConstants.ql:7,29-48) | module.py | 2 | ControlFlowNode for ImportExpr | import | true | | module.py | 2 | ControlFlowNode for sys | import | true | | module.py | 3 | ControlFlowNode for Compare | import | false | diff --git a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql index a4543881042..6215714a25e 100644 --- a/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql +++ b/python/ql/test/3/library-tests/PointsTo/consts/BooleanConstants.ql @@ -2,13 +2,8 @@ import python import semmle.python.pointsto.PointsTo from ControlFlowNode f, Context c, boolean b - -where -exists(Object obj | - PointsTo::points_to(f, c, obj, _, _) and obj.booleanValue() = b -) and -not exists(Object obj | - PointsTo::points_to(f, c, obj, _, _) and not obj.booleanValue() = b -) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), c.toString(), b +where + exists(Object obj | PointsTo::points_to(f, c, obj, _, _) and obj.booleanValue() = b) and + not exists(Object obj | PointsTo::points_to(f, c, obj, _, _) and not obj.booleanValue() = b) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + c.toString(), b diff --git a/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql b/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql index 844992f663e..d07dc65c34f 100644 --- a/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql +++ b/python/ql/test/3/library-tests/PointsTo/import_time/Pruned.ql @@ -1,7 +1,9 @@ - import python import semmle.python.pointsto.PointsTo from ControlFlowNode f, Location l -where not PointsToInternal::reachableBlock(f.getBasicBlock(), _) and l = f.getLocation() and l.getFile().getShortName() = "test.py" +where + not PointsToInternal::reachableBlock(f.getBasicBlock(), _) and + l = f.getLocation() and + l.getFile().getShortName() = "test.py" select l.getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql index d35ac04bb30..f91d207fc70 100644 --- a/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/3/library-tests/PointsTo/inheritance/Calls.ql @@ -1,8 +1,5 @@ - import python from Call c, FunctionObject f - where f.getACall().getNode() = c - select c.getLocation().getStartLine(), f.toString(), f.getFunction().getLocation().getStartLine() diff --git a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql index b658eb84474..68eec976105 100644 --- a/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/3/library-tests/PointsTo/metaclass/test.ql @@ -1,4 +1,3 @@ - import python from ClassObject cls diff --git a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql index b6f1ce2da98..e21a864b8bb 100644 --- a/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql +++ b/python/ql/test/3/library-tests/PointsTo/regressions/subprocess-assert/ClassValue.ql @@ -1,10 +1,11 @@ import python // as used in semmle.python.filters.Tests - from ClassValue c, string base where c.getScope().getLocation().getFile().getShortName().matches("mwe%.py") and c.getName() = "MyTest" and - if exists(c.getABaseType()) then base = c.getABaseType().toString() else base = "" + if exists(c.getABaseType()) + then base = c.getABaseType().toString() + else base = "" select c, base diff --git a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql index d8e877aa437..8716d38f086 100644 --- a/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql +++ b/python/ql/test/3/library-tests/PointsTo/typehints/Values.ql @@ -1,8 +1,7 @@ - import python from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin where - f.pointsTo(ctx, v, origin) and - f.getLocation().getFile().getBaseName() = "test.py" + f.pointsTo(ctx, v, origin) and + f.getLocation().getFile().getBaseName() = "test.py" select f.getLocation(), f.toString(), ctx, v diff --git a/python/ql/test/3/library-tests/classes/attr/class_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/3/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/3/library-tests/classes/meta/meta.ql b/python/ql/test/3/library-tests/classes/meta/meta.ql index c295fc330f2..96e26b3f060 100644 --- a/python/ql/test/3/library-tests/classes/meta/meta.ql +++ b/python/ql/test/3/library-tests/classes/meta/meta.ql @@ -1,4 +1,4 @@ import python from ClassExpr cls -select cls.toString(), cls.getMetaClass().toString() \ No newline at end of file +select cls.toString(), cls.getMetaClass().toString() diff --git a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql index f4f91869069..e85127a9305 100644 --- a/python/ql/test/3/library-tests/classes/meta/meta_obj.ql +++ b/python/ql/test/3/library-tests/classes/meta/meta_obj.ql @@ -2,4 +2,4 @@ import python from ClassObject cls where not cls.isC() -select cls.toString(), cls.getAnInferredType().toString() \ No newline at end of file +select cls.toString(), cls.getAnInferredType().toString() diff --git a/python/ql/test/3/library-tests/classes/mro/mro.ql b/python/ql/test/3/library-tests/classes/mro/mro.ql index 87f7e35c7bc..2c710a18eeb 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro.ql @@ -7,6 +7,7 @@ import python from ClassObject cls, ClassObject l, ClassObject r -where not cls.isC() and -r = cls.nextInMro(l) +where + not cls.isC() and + r = cls.nextInMro(l) select cls.toString(), l.toString(), r.toString() diff --git a/python/ql/test/3/library-tests/classes/mro/mro_index.ql b/python/ql/test/3/library-tests/classes/mro/mro_index.ql index f8398bcb737..641667e28f1 100644 --- a/python/ql/test/3/library-tests/classes/mro/mro_index.ql +++ b/python/ql/test/3/library-tests/classes/mro/mro_index.ql @@ -7,6 +7,7 @@ import python from ClassObject cls, ClassObject sup, int index -where sup = cls.getMroItem(index) and -not cls.isC() +where + sup = cls.getMroItem(index) and + not cls.isC() select cls.toString(), index, sup.toString() diff --git a/python/ql/test/3/library-tests/locations/annotations/Locations.ql b/python/ql/test/3/library-tests/locations/annotations/Locations.ql index 66428d5e8ad..211f6ee47df 100644 --- a/python/ql/test/3/library-tests/locations/annotations/Locations.ql +++ b/python/ql/test/3/library-tests/locations/annotations/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode a, Location l where a.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn(), a.toString() diff --git a/python/ql/test/3/library-tests/locations/general/AllLocations.ql b/python/ql/test/3/library-tests/locations/general/AllLocations.ql index 981d4560d87..9e6fcb00a05 100644 --- a/python/ql/test/3/library-tests/locations/general/AllLocations.ql +++ b/python/ql/test/3/library-tests/locations/general/AllLocations.ql @@ -9,8 +9,7 @@ import python from string classname where -exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) -or -exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) - + exists(AstNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) + or + exists(ControlFlowNode node | not exists(node.getLocation()) and classname = node.getAQlClass()) select classname diff --git a/python/ql/test/3/library-tests/locations/general/Locations.ql b/python/ql/test/3/library-tests/locations/general/Locations.ql index 874eecbdb9f..b2e7f4b164d 100644 --- a/python/ql/test/3/library-tests/locations/general/Locations.ql +++ b/python/ql/test/3/library-tests/locations/general/Locations.ql @@ -1,6 +1,5 @@ import python - from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/3/library-tests/locations/general/Prefix.ql b/python/ql/test/3/library-tests/locations/general/Prefix.ql index ad608f84cc2..bee9e555cc6 100644 --- a/python/ql/test/3/library-tests/locations/general/Prefix.ql +++ b/python/ql/test/3/library-tests/locations/general/Prefix.ql @@ -1,5 +1,4 @@ import python - -from StrConst s -select s.getLocation().getStartLine(), s.getText(), s.getPrefix() \ No newline at end of file +from StrConst s +select s.getLocation().getStartLine(), s.getText(), s.getPrefix() diff --git a/python/ql/test/3/library-tests/locations/keywords/Locations.ql b/python/ql/test/3/library-tests/locations/keywords/Locations.ql index b638ea81e14..afe685d0864 100644 --- a/python/ql/test/3/library-tests/locations/keywords/Locations.ql +++ b/python/ql/test/3/library-tests/locations/keywords/Locations.ql @@ -1,6 +1,5 @@ import python - from Keyword k, Location l where k.getLocation() = l -select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/3/library-tests/modules/general/import_test.ql b/python/ql/test/3/library-tests/modules/general/import_test.ql index 026dcf2c690..94f8c1447ca 100644 --- a/python/ql/test/3/library-tests/modules/general/import_test.ql +++ b/python/ql/test/3/library-tests/modules/general/import_test.ql @@ -1,7 +1,9 @@ import python from ImportExpr ie, string m, string t, string r -where m = ie.getImportedModuleName() and -(if ie.isTop() then t = "top" else t = "bottom") and -(if ie.isRelative() then r= "relative" else r = "absolute") -select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, r, m +where + m = ie.getImportedModuleName() and + (if ie.isTop() then t = "top" else t = "bottom") and + (if ie.isRelative() then r = "relative" else r = "absolute") +select ie.getScope().toString(), ie.getLocation().getStartLine(), ie.toString(), ie.getLevel(), t, + r, m diff --git a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql index 39c8aaab471..a3a1ac6b185 100644 --- a/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql +++ b/python/ql/test/3/library-tests/modules/general/moduleobject_test.ql @@ -1,4 +1,3 @@ - import python from ModuleObject m, string name diff --git a/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql b/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql +++ b/python/ql/test/3/library-tests/taint/unpacking/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/3/library-tests/types/classes/mro_test.ql b/python/ql/test/3/library-tests/types/classes/mro_test.ql index cb067035076..04b65ae2bef 100644 --- a/python/ql/test/3/library-tests/types/classes/mro_test.ql +++ b/python/ql/test/3/library-tests/types/classes/mro_test.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls, ClassObject sup where not cls.isC() select cls.toString(), sup.toString(), cls.nextInMro(sup).toString() - diff --git a/python/ql/test/3/library-tests/types/exceptions/Raises.ql b/python/ql/test/3/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/3/library-tests/types/exceptions/Viable.ql b/python/ql/test/3/library-tests/types/exceptions/Viable.ql index 544b0a0d0b6..e28fa1a907c 100644 --- a/python/ql/test/3/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/3/library-tests/types/exceptions/Viable.ql @@ -1,7 +1,6 @@ - - import python from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge(n, ex) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), ex.toString() +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), ex.toString() diff --git a/python/ql/test/3/library-tests/types/functions/Calls.ql b/python/ql/test/3/library-tests/types/functions/Calls.ql index 608ad79bdfb..6fc188753e5 100644 --- a/python/ql/test/3/library-tests/types/functions/Calls.ql +++ b/python/ql/test/3/library-tests/types/functions/Calls.ql @@ -1,7 +1,5 @@ - import python from FunctionObject func, ControlFlowNode call where func.getACall() = call select call.getLocation().getStartLine(), call.toString(), func.toString() - diff --git a/python/ql/test/3/library-tests/types/functions/Never.ql b/python/ql/test/3/library-tests/types/functions/Never.ql index 3dcf47ffd4d..1e43ead7dce 100644 --- a/python/ql/test/3/library-tests/types/functions/Never.ql +++ b/python/ql/test/3/library-tests/types/functions/Never.ql @@ -2,4 +2,4 @@ import python from FunctionObject func where func.neverReturns() -select func.getOrigin().getLocation().getStartLine(), func.getName() \ No newline at end of file +select func.getOrigin().getLocation().getStartLine(), func.getName() diff --git a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql index a200a947ab0..beb955e1188 100644 --- a/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql +++ b/python/ql/test/3/library-tests/types/functions/ReturnTypes.ql @@ -1,7 +1,5 @@ - import python from PyFunctionObject func, ClassObject ret_type where func.getAnInferredReturnType() = ret_type - select func.getOrigin().getLocation().getStartLine(), func.getName(), ret_type.toString() diff --git a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql index 6997fd80635..4a35fae7e8b 100644 --- a/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql +++ b/python/ql/test/3/library-tests/types/namespaces/NameSpace.ql @@ -8,17 +8,17 @@ import python from Scope s, string name, Object val -where name != "__name__" and -( - exists(ModuleObject m | - m.getModule() = s and - m.attributeRefersTo(name, val, _) - ) - or - exists(ClassObject cls | - cls.getPyClass() = s and - cls.declaredAttribute(name) = val - ) -) - -select s.toString(), name, val.toString() \ No newline at end of file +where + name != "__name__" and + ( + exists(ModuleObject m | + m.getModule() = s and + m.attributeRefersTo(name, val, _) + ) + or + exists(ClassObject cls | + cls.getPyClass() = s and + cls.declaredAttribute(name) = val + ) + ) +select s.toString(), name, val.toString() diff --git a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql index 7fd60f2e058..6ff0563e787 100644 --- a/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql +++ b/python/ql/test/3/library-tests/types/properties/BuiltinProperties.ql @@ -1,7 +1,8 @@ import python from ClassObject cls, string name, BuiltinPropertyObject p -where cls.declaredAttribute(name) = p and -(cls = theObjectType() or cls = theListType() or cls = theTypeType()) - -select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), p.getDeleter().toString() +where + cls.declaredAttribute(name) = p and + (cls = theObjectType() or cls = theListType() or cls = theTypeType()) +select cls.toString(), name, p.toString(), p.getGetter().toString(), p.getSetter().toString(), + p.getDeleter().toString() diff --git a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql index 41efa249c31..54e7ed36333 100644 --- a/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql +++ b/python/ql/test/library-tests/ControlFlow/PointsToSupport/UseFromDefinition.ql @@ -1,17 +1,15 @@ - import python /*Find any Definition, assigned value pairs that 'valueForDefinition' misses */ - Expr assignedValue(Name n) { exists(Assign a | a.getATarget() = n and result = a.getValue()) or exists(Alias a | a.getAsname() = n and result = a.getValue()) } -from Name def, DefinitionNode d -where d = def.getAFlowNode() and - exists(assignedValue(def)) and - not d.getValue().getNode() = assignedValue(def) - -select def.toString(), assignedValue(def) \ No newline at end of file +from Name def, DefinitionNode d +where + d = def.getAFlowNode() and + exists(assignedValue(def)) and + not d.getValue().getNode() = assignedValue(def) +select def.toString(), assignedValue(def) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql b/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql index d356ea5de43..a4b98183c27 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/AugAssignFlow.ql @@ -1,10 +1,10 @@ import python -int lineof(ControlFlowNode f) { - result = f.getNode().getLocation().getStartLine() -} +int lineof(ControlFlowNode f) { result = f.getNode().getLocation().getStartLine() } from ControlFlowNode defn, ControlFlowNode use -where defn.getNode() = use.getNode() -and defn.isStore() and use.isLoad() +where + defn.getNode() = use.getNode() and + defn.isStore() and + use.isLoad() select defn.toString(), use.toString(), lineof(defn) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql b/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql index 8ac3a4de0c1..c97f8446345 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/Kind.ql @@ -1,21 +1,16 @@ - import python string kind(ControlFlowNode f) { - if f.isAugLoad() then - result = "aug load" + if f.isAugLoad() + then result = "aug load" else ( - if f.isAugStore() then - result = "aug store" + if f.isAugStore() + then result = "aug store" else ( - if f.isLoad() then - result = "load" - else ( - f.isStore() and result = "store" - ) + if f.isLoad() then result = "load" else (f.isStore() and result = "store") ) - ) + ) } from ControlFlowNode cfg -select cfg.getLocation().getStartLine(), cfg, kind(cfg) \ No newline at end of file +select cfg.getLocation().getStartLine(), cfg, kind(cfg) diff --git a/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql b/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql index 7706226bcfa..0222099924b 100644 --- a/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql +++ b/python/ql/test/library-tests/ControlFlow/augassign/SSA.ql @@ -7,7 +7,6 @@ import python - from ControlFlowNode defn, SsaVariable v, AugAssign a, BinaryExpr b -where v.getDefinition() = defn and a.getOperation() = b and b.contains((Expr)defn.getNode()) -select defn.toString(), defn.getNode().getLocation().getStartLine() \ No newline at end of file +where v.getDefinition() = defn and a.getOperation() = b and b.contains(defn.getNode().(Expr)) +select defn.toString(), defn.getNode().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql b/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql index 5e66d239419..13e4736e6d9 100644 --- a/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql +++ b/python/ql/test/library-tests/ControlFlow/comparison/Compare.ql @@ -8,10 +8,11 @@ import python from CompareNode c, NameNode l, NameNode r, Cmpop op, int line, Variable vl, Variable vr -where c.operands(l, op, r) and -line = c.getLocation().getStartLine() and -line = l.getLocation().getStartLine() and -line = r.getLocation().getStartLine() and -l.uses(vl) and r.uses(vr) +where + c.operands(l, op, r) and + line = c.getLocation().getStartLine() and + line = l.getLocation().getStartLine() and + line = r.getLocation().getStartLine() and + l.uses(vl) and + r.uses(vr) select line, c.toString(), vl.getId(), vr.getId(), op.getSymbol() - diff --git a/python/ql/test/library-tests/ControlFlow/delete/test.ql b/python/ql/test/library-tests/ControlFlow/delete/test.ql index 517733b70d6..2aaa45ea719 100644 --- a/python/ql/test/library-tests/ControlFlow/delete/test.ql +++ b/python/ql/test/library-tests/ControlFlow/delete/test.ql @@ -2,4 +2,5 @@ import python from ControlFlowNode p, ControlFlowNode s where p.getASuccessor() = s -select p.getLocation().getStartLine().toString(), p.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +select p.getLocation().getStartLine().toString(), p.toString(), s.getLocation().getStartLine(), + s.toString() diff --git a/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql b/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql index cb53879e63b..d39328e44c7 100644 --- a/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql +++ b/python/ql/test/library-tests/ControlFlow/dominators/DominatesSanity.ql @@ -1,9 +1,8 @@ - import python -select count(BasicBlock b1, BasicBlock b2 -| b1 = b2.getImmediateDominator+() and not b1.strictlyDominates(b2) -), -count(BasicBlock b1, BasicBlock b2 -| not b1 = b2.getImmediateDominator+() and b1.strictlyDominates(b2) -) +select count(BasicBlock b1, BasicBlock b2 | + b1 = b2.getImmediateDominator+() and not b1.strictlyDominates(b2) + ), + count(BasicBlock b1, BasicBlock b2 | + not b1 = b2.getImmediateDominator+() and b1.strictlyDominates(b2) + ) diff --git a/python/ql/test/library-tests/ControlFlow/dominators/idom.ql b/python/ql/test/library-tests/ControlFlow/dominators/idom.ql index 940624c6b20..cd948b6ff10 100644 --- a/python/ql/test/library-tests/ControlFlow/dominators/idom.ql +++ b/python/ql/test/library-tests/ControlFlow/dominators/idom.ql @@ -8,9 +8,8 @@ import python /* This query should *never* produce a result */ - from ControlFlowNode f -where not exists(f.getImmediateDominator()) -and not f.getNode() instanceof Scope +where + not exists(f.getImmediateDominator()) and + not f.getNode() instanceof Scope select f - diff --git a/python/ql/test/library-tests/ControlFlow/general/Comments.ql b/python/ql/test/library-tests/ControlFlow/general/Comments.ql index e93c8aae330..71d00f1a8d4 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Comments.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Comments.ql @@ -3,4 +3,3 @@ import python from Module m, int n where n = m.getMetrics().getNumberOfLinesOfComments() select m.toString(), n - diff --git a/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql b/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql index 6ca0327ab0b..fb801a29002 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Cyclo.ql @@ -2,5 +2,3 @@ import python from Function func select func.toString(), func.getMetrics().getCyclomaticComplexity() - - diff --git a/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql b/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql index f038fd8d77a..66758604be2 100644 --- a/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql +++ b/python/ql/test/library-tests/ControlFlow/general/ImmediateDominatorCheck.ql @@ -1,16 +1,19 @@ - - import python -predicate -can_reach_from_entry_without_passing(ControlFlowNode target, ControlFlowNode pass) { - target != pass and target.getScope() = pass.getScope() and - (target.isEntryNode() or - exists(ControlFlowNode pre | target.getAPredecessor() = pre and can_reach_from_entry_without_passing(pre, pass))) +predicate can_reach_from_entry_without_passing(ControlFlowNode target, ControlFlowNode pass) { + target != pass and + target.getScope() = pass.getScope() and + ( + target.isEntryNode() + or + exists(ControlFlowNode pre | + target.getAPredecessor() = pre and can_reach_from_entry_without_passing(pre, pass) + ) + ) } from ControlFlowNode node, ControlFlowNode dom -where dom = node.getImmediateDominator() -and -can_reach_from_entry_without_passing(node, dom) +where + dom = node.getImmediateDominator() and + can_reach_from_entry_without_passing(node, dom) select node.toString(), dom.toString() diff --git a/python/ql/test/library-tests/ControlFlow/general/Lines.ql b/python/ql/test/library-tests/ControlFlow/general/Lines.ql index 60046ef3242..dabbe2bbf58 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Lines.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Lines.ql @@ -1,7 +1,8 @@ import python from Scope s, int n -where exists(Function f | f = s | n = f.getMetrics().getNumberOfLines()) or -exists(Module m | m = s | n = m.getMetrics().getNumberOfLines()) +where + exists(Function f | f = s | n = f.getMetrics().getNumberOfLines()) + or + exists(Module m | m = s | n = m.getMetrics().getNumberOfLines()) select s.toString(), n - diff --git a/python/ql/test/library-tests/ControlFlow/general/Reaches.ql b/python/ql/test/library-tests/ControlFlow/general/Reaches.ql index 548be578a76..3412e6a99bd 100644 --- a/python/ql/test/library-tests/ControlFlow/general/Reaches.ql +++ b/python/ql/test/library-tests/ControlFlow/general/Reaches.ql @@ -1,9 +1,8 @@ import python predicate reaches_exit(Name u) { - u.uses(_) and - exists(ControlFlowNode f, BasicBlock b | - f.getNode() = u and f.getBasicBlock() = b | + u.uses(_) and + exists(ControlFlowNode f, BasicBlock b | f.getNode() = u and f.getBasicBlock() = b | b.reachesExit() ) } diff --git a/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql b/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql index bfc884f7bac..35e43acaa12 100644 --- a/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql +++ b/python/ql/test/library-tests/ControlFlow/raising_stmts/RaisingFlow.ql @@ -6,12 +6,10 @@ import python from ControlFlowNode p, ControlFlowNode s, string kind -where p.getASuccessor() = s and -(if s = p.getAnExceptionalSuccessor() then - kind = "exception" - else - kind = " normal " -) and -not p.getNode() instanceof Scope and -not s.getNode() instanceof Scope -select p.getNode().getLocation().getStartLine(), p.toString(), kind, s.getNode().getLocation().getStartLine(), s +where + p.getASuccessor() = s and + (if s = p.getAnExceptionalSuccessor() then kind = "exception" else kind = " normal ") and + not p.getNode() instanceof Scope and + not s.getNode() instanceof Scope +select p.getNode().getLocation().getStartLine(), p.toString(), kind, + s.getNode().getLocation().getStartLine(), s diff --git a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql index d9d5efbb494..c743952f2b1 100644 --- a/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql +++ b/python/ql/test/library-tests/ControlFlow/splitting/NodeCount.ql @@ -1,8 +1,11 @@ import python from AstNode a, Scope s -where not a instanceof Import and not a instanceof If and not a instanceof AssignStmt and not a instanceof ExprStmt and -a.getScope() = s and -s instanceof Function -select -a.getLocation().getStartLine(), s.getName(), a, count(a.getAFlowNode()) +where + not a instanceof Import and + not a instanceof If and + not a instanceof AssignStmt and + not a instanceof ExprStmt and + a.getScope() = s and + s instanceof Function +select a.getLocation().getStartLine(), s.getName(), a, count(a.getAFlowNode()) diff --git a/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql b/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql index d865d9061c3..0941d2f2024 100644 --- a/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql +++ b/python/ql/test/library-tests/ControlFlow/splitting/SuccessorCount.ql @@ -1,9 +1,8 @@ import python from ControlFlowNode p, Scope s -where -p.getScope() = s and -(exists (p.getATrueSuccessor()) or exists(p.getAFalseSuccessor())) and -s instanceof Function -select -p.getLocation().getStartLine(), s.getName(), p, strictcount(p.getASuccessor()) +where + p.getScope() = s and + (exists(p.getATrueSuccessor()) or exists(p.getAFalseSuccessor())) and + s instanceof Function +select p.getLocation().getStartLine(), s.getName(), p, strictcount(p.getASuccessor()) diff --git a/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql index c8ce2855455..d4cff3d6122 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/defns/test.ql @@ -2,5 +2,5 @@ import python from SsaVariable var, SsaVariable def where def = var.getAnUltimateDefinition() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), def, def.getLocation().getStartLine() +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + def, def.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql index b220553d07b..feafac5a6c7 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/deletions/test.ql @@ -1,14 +1,13 @@ import python - from SsaVariable v, string kind, ControlFlowNode use, int line -where use = v.getAUse() and -( - kind = "delete" and v.getDefinition().isDelete() - or - kind = "other " and not v.getDefinition().isDelete() -) -and line = use.getLocation().getStartLine() -and line != 0 - +where + use = v.getAUse() and + ( + kind = "delete" and v.getDefinition().isDelete() + or + kind = "other " and not v.getDefinition().isDelete() + ) and + line = use.getLocation().getStartLine() and + line != 0 select line, use.toString(), v.getId(), kind diff --git a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql index 5cfb210da24..fb2c8f20da8 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/phi_input_test.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, SsaVariable arg, BasicBlock pred where pred = var.getPredecessorBlockForPhiArgument(arg) -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), arg, arg.getLocation().getStartLine(), pred.getLastNode().getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + arg, arg.getLocation().getStartLine(), pred.getLastNode().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql index 6c4f617e172..a8aef8cc72d 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/phi-nodes/test.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, SsaVariable arg where arg = var.getAPhiInput() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), arg, arg.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + arg, arg.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql index df5df70d827..41b08ec0591 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/undefined/test.ql @@ -1,7 +1,5 @@ - import python from SsaVariable var where var.maybeUndefined() -select -var.getDefinition().getLocation().getStartLine(), var.toString() +select var.getDefinition().getLocation().getStartLine(), var.toString() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql index 9a3f4e92452..e120b6e1657 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/uses/test.ql @@ -2,5 +2,5 @@ import python from ControlFlowNode use, SsaVariable def where def.getAUse() = use -select use.getLocation().getFile().getShortName(), -use.toString(), use.getLocation().getStartLine(), def.toString(), def.getLocation().getStartLine() +select use.getLocation().getFile().getShortName(), use.toString(), use.getLocation().getStartLine(), + def.toString(), def.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql b/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql index 5e2dd530ad9..1892974be9b 100644 --- a/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql +++ b/python/ql/test/library-tests/ControlFlow/ssa/vars/test.ql @@ -1,7 +1,4 @@ import python from SsaVariable var - -select var.getLocation().getFile().getShortName(), -var, var.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var, var.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/ControlFlow/successors/Successors.ql b/python/ql/test/library-tests/ControlFlow/successors/Successors.ql index 20567e057d1..802ed60962b 100644 --- a/python/ql/test/library-tests/ControlFlow/successors/Successors.ql +++ b/python/ql/test/library-tests/ControlFlow/successors/Successors.ql @@ -3,16 +3,15 @@ import semmle.python.TestUtils from ControlFlowNode p, ControlFlowNode s, string what where -s = p.getAFalseSuccessor() and what = "false" -or -s = p.getATrueSuccessor() and what = "true" -or -s = p.getAnExceptionalSuccessor() and what = "exceptional" -or -s = p.getANormalSuccessor() and what = "normal" -or -// Add fake edges for node that raise out of scope -p.isExceptionalExit(_) and s = p.getScope().getEntryNode() and what = "exit" - -select compact_location(p.getNode()), p.getNode().toString(), - compact_location(s.getNode()), s.getNode().toString(), what + s = p.getAFalseSuccessor() and what = "false" + or + s = p.getATrueSuccessor() and what = "true" + or + s = p.getAnExceptionalSuccessor() and what = "exceptional" + or + s = p.getANormalSuccessor() and what = "normal" + or + // Add fake edges for node that raise out of scope + p.isExceptionalExit(_) and s = p.getScope().getEntryNode() and what = "exit" +select compact_location(p.getNode()), p.getNode().toString(), compact_location(s.getNode()), + s.getNode().toString(), what diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql b/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql index 163f57bcd06..352b1d2890d 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/ExceptionalSuccessors.ql @@ -9,8 +9,8 @@ import python from ControlFlowNode p, ControlFlowNode s where -s = p.getAnExceptionalSuccessor() -or -// Add fake edges for node that raise out of scope -p.isExceptionalExit(_) and s = p.getScope().getEntryNode() + s = p.getAnExceptionalSuccessor() + or + // Add fake edges for node that raise out of scope + p.isExceptionalExit(_) and s = p.getScope().getEntryNode() select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString() diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql b/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql index d5d8323a3a2..b2ca6cbd5ca 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/TrueAndFalseSuccessor.ql @@ -1,7 +1,5 @@ - - import python from ControlFlowNode f where f.getATrueSuccessor() = f.getAFalseSuccessor() -select f.toString() \ No newline at end of file +select f.toString() diff --git a/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql b/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql index 3320f06b8c7..1dedb90ea49 100644 --- a/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql +++ b/python/ql/test/library-tests/ControlFlow/truefalse/TrueFalseSuccessors.ql @@ -9,7 +9,8 @@ import python from ControlFlowNode p, ControlFlowNode s, string which where -s = p.getAFalseSuccessor() and which = "False" -or -s = p.getATrueSuccessor() and which = "True" -select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString(), which + s = p.getAFalseSuccessor() and which = "False" + or + s = p.getATrueSuccessor() and which = "True" +select p.getLocation().getFile().getShortName(), p.getLocation().getStartLine(), p, s.toString(), + which diff --git a/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql b/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql index 8df422495fb..8ac7583b627 100644 --- a/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql +++ b/python/ql/test/library-tests/ControlFlow/try/test_ssa.ql @@ -2,6 +2,5 @@ import python from SsaVariable var, ControlFlowNode use where use = var.getAUse() -select var.getLocation().getFile().getShortName(), -var.toString(), var.getLocation().getStartLine(), use.toString(), use.getLocation().getStartLine() - +select var.getLocation().getFile().getShortName(), var.toString(), var.getLocation().getStartLine(), + use.toString(), use.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DefUse/Definitions.ql b/python/ql/test/library-tests/DefUse/Definitions.ql index 049bb7b9a82..52b00f42146 100644 --- a/python/ql/test/library-tests/DefUse/Definitions.ql +++ b/python/ql/test/library-tests/DefUse/Definitions.ql @@ -9,4 +9,4 @@ import python from Name d where d.defines(_) -select d.getId(), d.getLocation().getStartLine() \ No newline at end of file +select d.getId(), d.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DefUse/Uses.ql b/python/ql/test/library-tests/DefUse/Uses.ql index bb02c6b5fac..ada93f740fb 100644 --- a/python/ql/test/library-tests/DefUse/Uses.ql +++ b/python/ql/test/library-tests/DefUse/Uses.ql @@ -9,4 +9,4 @@ import python from Name u where u.uses(_) -select u.getId(), u.getLocation().getStartLine() \ No newline at end of file +select u.getId(), u.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/DuplicateCode/Duplicate.ql b/python/ql/test/library-tests/DuplicateCode/Duplicate.ql index dfa9c11bf68..c680d481398 100644 --- a/python/ql/test/library-tests/DuplicateCode/Duplicate.ql +++ b/python/ql/test/library-tests/DuplicateCode/Duplicate.ql @@ -6,16 +6,18 @@ */ import python - import external.CodeDuplication predicate lexically_sorted(DuplicateBlock dup1, DuplicateBlock dup2) { - dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() - or - dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and dup1.sourceStartLine() < dup2.sourceStartLine() + dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() + or + dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and + dup1.sourceStartLine() < dup2.sourceStartLine() } from DuplicateBlock dup1, DuplicateBlock dup2 -where dup1.getEquivalenceClass() = dup2.getEquivalenceClass() -and lexically_sorted(dup1, dup2) -select dup1.toString(), dup2.toString(), dup1.sourceFile().getShortName(), dup1.sourceStartLine(), dup1.sourceEndLine() +where + dup1.getEquivalenceClass() = dup2.getEquivalenceClass() and + lexically_sorted(dup1, dup2) +select dup1.toString(), dup2.toString(), dup1.sourceFile().getShortName(), dup1.sourceStartLine(), + dup1.sourceEndLine() diff --git a/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql b/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql index a4243bca968..17904ea65cd 100644 --- a/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql +++ b/python/ql/test/library-tests/DuplicateCode/DuplicateStatements.ql @@ -10,16 +10,17 @@ import external.CodeDuplication predicate mostlyDuplicateFunction(Function f) { exists(int covered, int total, Function other, int percent | - duplicateStatements(f, other, covered, total) and - covered != total and - total > 5 and - covered * 100 / total = percent and - percent > 80 and - not exists(Scope s | s = f.getScope*() | duplicateScopes(s, _, _, _)) + duplicateStatements(f, other, covered, total) and + covered != total and + total > 5 and + covered * 100 / total = percent and + percent > 80 and + not exists(Scope s | s = f.getScope*() | duplicateScopes(s, _, _, _)) ) } from Stmt s -where mostlyDuplicateFunction(s.getScope()) and -not duplicateStatement(s.getScope(), _, s, _) -select s.toString(), s.getLocation().toString() \ No newline at end of file +where + mostlyDuplicateFunction(s.getScope()) and + not duplicateStatement(s.getScope(), _, s, _) +select s.toString(), s.getLocation().toString() diff --git a/python/ql/test/library-tests/DuplicateCode/Similar.ql b/python/ql/test/library-tests/DuplicateCode/Similar.ql index 338ec5602ef..528908336d8 100644 --- a/python/ql/test/library-tests/DuplicateCode/Similar.ql +++ b/python/ql/test/library-tests/DuplicateCode/Similar.ql @@ -6,16 +6,17 @@ */ import python - import external.CodeDuplication predicate lexically_sorted(SimilarBlock dup1, SimilarBlock dup2) { - dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() - or - dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and dup1.sourceStartLine() < dup2.sourceStartLine() + dup1.sourceFile().getAbsolutePath() < dup2.sourceFile().getAbsolutePath() + or + dup1.sourceFile().getAbsolutePath() = dup2.sourceFile().getAbsolutePath() and + dup1.sourceStartLine() < dup2.sourceStartLine() } from SimilarBlock dup1, SimilarBlock dup2 -where dup1.getEquivalenceClass() = dup2.getEquivalenceClass() -and lexically_sorted(dup1, dup2) +where + dup1.getEquivalenceClass() = dup2.getEquivalenceClass() and + lexically_sorted(dup1, dup2) select dup1, dup2, dup1.sourceFile().getShortName(), dup1.sourceStartLine(), dup1.sourceEndLine() diff --git a/python/ql/test/library-tests/PointsTo/absent/Absent.ql b/python/ql/test/library-tests/PointsTo/absent/Absent.ql index d21c2b339ae..95cdf3a1084 100644 --- a/python/ql/test/library-tests/PointsTo/absent/Absent.ql +++ b/python/ql/test/library-tests/PointsTo/absent/Absent.ql @@ -1,8 +1,6 @@ - import python import semmle.python.objects.Modules from Value val, ControlFlowNode f where f.pointsTo(val) select f, val - diff --git a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql index 1c0c53d0bcd..a71380b7603 100644 --- a/python/ql/test/library-tests/PointsTo/api/ClassValue.ql +++ b/python/ql/test/library-tests/PointsTo/api/ClassValue.ql @@ -11,5 +11,4 @@ where cls = ClassValue::classmethod() and description = "classmethod" or cls = ClassValue::bool().getMro().getItem(2) and description = "object" - -select cls, description \ No newline at end of file +select cls, description diff --git a/python/ql/test/library-tests/PointsTo/api/Constants.ql b/python/ql/test/library-tests/PointsTo/api/Constants.ql index 73ff6750c4d..39763e6fc24 100644 --- a/python/ql/test/library-tests/PointsTo/api/Constants.ql +++ b/python/ql/test/library-tests/PointsTo/api/Constants.ql @@ -1,20 +1,16 @@ - import python from string txt, Value val where -exists(string s | - txt = "u'" + s + "'" and val = Value::forUnicode(s) + exists(string s | + txt = "u'" + s + "'" and val = Value::forUnicode(s) + or + txt = "b'" + s + "'" and val = Value::forBytes(s) + | + s = "a" or s = "b" or s = "c" or s = "d" + ) or - txt = "b'" + s + "'" and val = Value::forBytes(s) - | - s = "a" or s = "b" or s = "c" or s = "d" -) -or -exists(int i | - txt = i.toString() and val = Value::forInt(i) - | - i in [1..10] or i in [1000..1010] -) - + exists(int i | txt = i.toString() and val = Value::forInt(i) | + i in [1 .. 10] or i in [1000 .. 1010] + ) select txt, val diff --git a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql index 8c82e2d106f..226b2520521 100644 --- a/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql +++ b/python/ql/test/library-tests/PointsTo/api/QualifedNames.ql @@ -1,16 +1,15 @@ - import python from FunctionValue v, string name -where name = v.getQualifiedName() and -( - v = Value::named("len") - or - v instanceof PythonFunctionValue - or - v = Value::named("sys.exit") - or - v = Value::named("list").(ClassValue).lookup("append") -) - -select v, name \ No newline at end of file +where + name = v.getQualifiedName() and + ( + v = Value::named("len") + or + v instanceof PythonFunctionValue + or + v = Value::named("sys.exit") + or + v = Value::named("list").(ClassValue).lookup("append") + ) +select v, name diff --git a/python/ql/test/library-tests/PointsTo/api/Value.ql b/python/ql/test/library-tests/PointsTo/api/Value.ql index 674dce5a299..23d78317764 100644 --- a/python/ql/test/library-tests/PointsTo/api/Value.ql +++ b/python/ql/test/library-tests/PointsTo/api/Value.ql @@ -2,11 +2,12 @@ import python from Value val, string name where - val = Value::named(name) - and + val = Value::named(name) and ( - name = "bool" or name = "sys" or name = "sys.argv" or - name = "ValueError" or name = "slice" + name = "bool" or + name = "sys" or + name = "sys.argv" or + name = "ValueError" or + name = "slice" ) - -select val, name \ No newline at end of file +select val, name diff --git a/python/ql/test/library-tests/PointsTo/calls/Argument.ql b/python/ql/test/library-tests/PointsTo/calls/Argument.ql index e88baf75791..1678c02c182 100644 --- a/python/ql/test/library-tests/PointsTo/calls/Argument.ql +++ b/python/ql/test/library-tests/PointsTo/calls/Argument.ql @@ -2,4 +2,4 @@ import python from ControlFlowNode arg, FunctionObject func, int i where arg = func.getArgumentForCall(_, i) -select arg.getLocation().getStartLine(), i, arg.toString(), func.toString() \ No newline at end of file +select arg.getLocation().getStartLine(), i, arg.toString(), func.toString() diff --git a/python/ql/test/library-tests/PointsTo/calls/Call.ql b/python/ql/test/library-tests/PointsTo/calls/Call.ql index d1cfbdad690..94c4212cc64 100644 --- a/python/ql/test/library-tests/PointsTo/calls/Call.ql +++ b/python/ql/test/library-tests/PointsTo/calls/Call.ql @@ -1,7 +1,5 @@ - import python from ControlFlowNode call, FunctionObject func - where call = func.getACall() -select call.getLocation().getStartLine(), call.toString(), func.toString() \ No newline at end of file +select call.getLocation().getStartLine(), call.toString(), func.toString() diff --git a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql index 804ae3a61df..958306c53e6 100644 --- a/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/comparisons/PointsTo.ql @@ -1,4 +1,3 @@ - import python import semmle.python.objects.ObjectAPI diff --git a/python/ql/test/library-tests/PointsTo/customise/test.expected b/python/ql/test/library-tests/PointsTo/customise/test.expected index 93c49242708..009572ad1c5 100644 --- a/python/ql/test/library-tests/PointsTo/customise/test.expected +++ b/python/ql/test/library-tests/PointsTo/customise/test.expected @@ -1,4 +1,4 @@ -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (test.ql:8,27-51) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (test.ql:9,27-51) | 9 | ControlFlowNode for has_type_int | Function has_type_int | builtin-class function | | 9 | ControlFlowNode for has_type_int() | has_type_int() | builtin-class int | | 9 | ControlFlowNode for x | has_type_int() | builtin-class int | diff --git a/python/ql/test/library-tests/PointsTo/customise/test.ql b/python/ql/test/library-tests/PointsTo/customise/test.ql index dca091e2e4f..8aea8b05b18 100644 --- a/python/ql/test/library-tests/PointsTo/customise/test.ql +++ b/python/ql/test/library-tests/PointsTo/customise/test.ql @@ -1,15 +1,15 @@ - import python import semmle.python.types.Extensions -/* Customise: Claim any function called has_type_XXX return any class +/* + * Customise: Claim any function called has_type_XXX return any class * whose name matches XXX */ -class HasTypeFact extends CustomPointsToOriginFact { +class HasTypeFact extends CustomPointsToOriginFact { HasTypeFact() { exists(FunctionObject func, string name | - func.getACall() = this and + func.getACall() = this and name = func.getName() and name.prefix("has_type_".length()) = "has_type_" ) @@ -17,19 +17,19 @@ class HasTypeFact extends CustomPointsToOriginFact { override predicate pointsTo(Object value, ClassObject cls) { exists(FunctionObject func, string name | - func.getACall() = this and + func.getACall() = this and name = func.getName() and - name.prefix("has_type_".length()) = "has_type_" | + name.prefix("has_type_".length()) = "has_type_" + | cls.getName() = name.suffix("has_type_".length()) ) and value = this } - } - from int line, ControlFlowNode f, Object o, ClassObject c -where f.getLocation().getStartLine() = line and - exists(Comment ct | ct.getLocation().getStartLine() < line) and - f.refersTo(o, c, _) +where + f.getLocation().getStartLine() = line and + exists(Comment ct | ct.getLocation().getStartLine() < line) and + f.refersTo(o, c, _) select line, f.toString(), o.toString(), c.toString() diff --git a/python/ql/test/library-tests/PointsTo/decorators/Test.ql b/python/ql/test/library-tests/PointsTo/decorators/Test.ql index af274849a26..3aff12a3a1f 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Test.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Test.ql @@ -3,9 +3,8 @@ import python // We don't care about the internals of functools which vary from // version to version, just the end result. from NameNode f, Object o, ControlFlowNode x, int line - -where f.refersTo(o, x) and -f.getLocation().getFile().getBaseName() = "test.py" and -line = f.getLocation().getStartLine() - +where + f.refersTo(o, x) and + f.getLocation().getFile().getBaseName() = "test.py" and + line = f.getLocation().getStartLine() select line, f.toString(), o.toString(), x.getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/decorators/Values.ql b/python/ql/test/library-tests/PointsTo/decorators/Values.ql index 2e752466c55..712cc025786 100644 --- a/python/ql/test/library-tests/PointsTo/decorators/Values.ql +++ b/python/ql/test/library-tests/PointsTo/decorators/Values.ql @@ -1,10 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from NameNode f, Context ctx, ObjectInternal v where - f.getLocation().getFile().getBaseName() = "test.py" and - PointsTo::pointsTo(f, ctx, v, _) + f.getLocation().getFile().getBaseName() = "test.py" and + PointsTo::pointsTo(f, ctx, v, _) select f, ctx, v diff --git a/python/ql/test/library-tests/PointsTo/extensions/Extend.expected b/python/ql/test/library-tests/PointsTo/extensions/Extend.expected index 791f854e105..0220ccb12ec 100644 --- a/python/ql/test/library-tests/PointsTo/extensions/Extend.expected +++ b/python/ql/test/library-tests/PointsTo/extensions/Extend.expected @@ -1,8 +1,8 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (Extend.ql:58,9-28) -WARNING: Type CustomPointsToAttribute has been deprecated and may be removed in future (Extend.ql:27,35-58) -WARNING: Type CustomPointsToObjectFact has been deprecated and may be removed in future (Extend.ql:42,32-56) -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:9,28-52) -WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:55,38-62) +WARNING: Predicate points_to has been deprecated and may be removed in future (Extend.ql:50,32-51) +WARNING: Type CustomPointsToAttribute has been deprecated and may be removed in future (Extend.ql:22,34-57) +WARNING: Type CustomPointsToObjectFact has been deprecated and may be removed in future (Extend.ql:38,32-56) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:5,28-52) +WARNING: Type CustomPointsToOriginFact has been deprecated and may be removed in future (Extend.ql:49,38-62) | test.py:4:1:4:3 | ControlFlowNode for one | int 1 | | test.py:5:1:5:3 | ControlFlowNode for two | int 2 | | test.py:8:1:8:1 | ControlFlowNode for IntegerLiteral | int 1 | diff --git a/python/ql/test/library-tests/PointsTo/extensions/Extend.ql b/python/ql/test/library-tests/PointsTo/extensions/Extend.ql index af4a696ea4f..14082905ce4 100644 --- a/python/ql/test/library-tests/PointsTo/extensions/Extend.ql +++ b/python/ql/test/library-tests/PointsTo/extensions/Extend.ql @@ -1,13 +1,8 @@ - - import python - import semmle.python.pointsto.PointsTo private import semmle.python.types.Extensions - class CfgExtension extends CustomPointsToOriginFact { - CfgExtension() { this.(NameNode).getId() = "one" or @@ -24,23 +19,23 @@ class CfgExtension extends CustomPointsToOriginFact { } } -class AttributeExtension extends CustomPointsToAttribute { - +class AttributeExtension extends CustomPointsToAttribute { AttributeExtension() { this = this } - override predicate attributePointsTo(string name, Object value, ClassObject cls, ControlFlowNode origin) { - cls = theIntType() and origin = any(Module m).getEntryNode() and + override predicate attributePointsTo( + string name, Object value, ClassObject cls, ControlFlowNode origin + ) { + cls = theIntType() and + origin = any(Module m).getEntryNode() and ( name = "three" and value.(NumericObject).intValue() = 3 or name = "four" and value.(NumericObject).intValue() = 4 ) } - } class NoClassExtension extends CustomPointsToObjectFact { - NoClassExtension() { this = this } override predicate pointsTo(Object value) { @@ -48,24 +43,17 @@ class NoClassExtension extends CustomPointsToObjectFact { or this.(NameNode).getId() = "six" and value.(NumericObject).intValue() = 6 } - } /* Check that we can use old API without causing non-monotonic recursion */ class RecurseIntoOldPointsTo extends CustomPointsToOriginFact { - - RecurseIntoOldPointsTo() { - PointsTo::points_to(this, _, unknownValue(), _, _) - } + RecurseIntoOldPointsTo() { PointsTo::points_to(this, _, unknownValue(), _, _) } override predicate pointsTo(Object value, ClassObject cls) { value = unknownValue() and cls = theUnknownType() } } - from ControlFlowNode f, Object o where f.getLocation().getFile().getBaseName() = "test.py" and f.refersTo(o) select f, o.toString() - - diff --git a/python/ql/test/library-tests/PointsTo/functions/Calls.ql b/python/ql/test/library-tests/PointsTo/functions/Calls.ql index 6f1e8cf8bd3..2833c2e60be 100644 --- a/python/ql/test/library-tests/PointsTo/functions/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/functions/Calls.ql @@ -1,12 +1,11 @@ - import python from CallNode call, FunctionObject func, string kind -where -(func.getAMethodCall() = call and kind = "method" - or - func.getAFunctionCall() = call and kind = "function" -) -and -call.getLocation().getFile().getShortName().matches("odasa%") +where + ( + func.getAMethodCall() = call and kind = "method" + or + func.getAFunctionCall() = call and kind = "function" + ) and + call.getLocation().getFile().getShortName().matches("odasa%") select call.getLocation().getStartLine(), call.toString(), func.toString(), kind diff --git a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql index ebb69fc7a0f..c576651a8e6 100644 --- a/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql +++ b/python/ql/test/library-tests/PointsTo/functions/NeverReturns.ql @@ -1,4 +1,3 @@ - import python from FunctionObject f diff --git a/python/ql/test/library-tests/PointsTo/functions/test.ql b/python/ql/test/library-tests/PointsTo/functions/test.ql index dd1a070d99f..f520f6b2254 100644 --- a/python/ql/test/library-tests/PointsTo/functions/test.ql +++ b/python/ql/test/library-tests/PointsTo/functions/test.ql @@ -1,9 +1,7 @@ import python from Call c, FunctionObject f - -where c.getFunc().(Attribute).getObject().(Name).getId() = "self" -and -f.getACall().getNode() = c - +where + c.getFunc().(Attribute).getObject().(Name).getId() = "self" and + f.getACall().getNode() = c select c.getLocation().getStartLine(), f.toString() diff --git a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql index 147b7835e24..a7b9403a18d 100644 --- a/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/GlobalPointsTo.ql @@ -1,10 +1,9 @@ - import python import interesting from int line, ControlFlowNode f, Object o, ImportTimeScope n -where -of_interest(f, line) and -f.refersTo(o) and -f.getScope() = n +where + of_interest(f, line) and + f.refersTo(o) and + f.getScope() = n select n.toString(), line, f.toString(), o.toString() diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql index 00144c87601..342a329746e 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsTo.ql @@ -10,7 +10,7 @@ import interesting import Util from int line, ControlFlowNode f, Object o -where - of_interest(f, line) and - f.refersTo(o) +where + of_interest(f, line) and + f.refersTo(o) select line, f.toString(), repr(o) diff --git a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql index 693d0b2b84b..c80de106c3d 100644 --- a/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql +++ b/python/ql/test/library-tests/PointsTo/general/LocalPointsToType.ql @@ -1,10 +1,9 @@ - import python import interesting import Util from int line, ControlFlowNode f, Object o, ClassObject cls -where - of_interest(f, line) and - f.refersTo(o, cls, _) +where + of_interest(f, line) and + f.refersTo(o, cls, _) select line, f.toString(), repr(o), repr(cls) diff --git a/python/ql/test/library-tests/PointsTo/general/interesting.qll b/python/ql/test/library-tests/PointsTo/general/interesting.qll index 2a5259dd176..f7c3e9d682d 100644 --- a/python/ql/test/library-tests/PointsTo/general/interesting.qll +++ b/python/ql/test/library-tests/PointsTo/general/interesting.qll @@ -1,4 +1,3 @@ - import python predicate of_interest(ControlFlowNode n, int line) { @@ -6,7 +5,7 @@ predicate of_interest(ControlFlowNode n, int line) { line = l.getStartLine() and f = l.getFile() and f.getName().matches("%test.py%") and - exists(Comment c | + exists(Comment c | c.getLocation().getStartLine() < line and c.getLocation().getFile() = f ) diff --git a/python/ql/test/library-tests/PointsTo/global/Global.ql b/python/ql/test/library-tests/PointsTo/global/Global.ql index 8aa0453645f..d9b8a246d11 100644 --- a/python/ql/test/library-tests/PointsTo/global/Global.ql +++ b/python/ql/test/library-tests/PointsTo/global/Global.ql @@ -1,14 +1,11 @@ - import python - - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import semmle.python.objects.ObjectInternal from ControlFlowNode f, PointsToContext ctx, Value obj, ControlFlowNode orig -where exists(ExprStmt s | s.getValue().getAFlowNode() = f) and -PointsTo::pointsTo(f, ctx, obj, orig) - +where + exists(ExprStmt s | s.getValue().getAFlowNode() = f) and + PointsTo::pointsTo(f, ctx, obj, orig) select ctx, f, obj.toString(), orig diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql index 98644b02e99..b545f6e6a18 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsTo.ql @@ -1,7 +1,8 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - -where f.refersTo(o, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, x) and + exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql index 83bbd5e42ba..2bf6b6b62a9 100644 --- a/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/guarded/PointsToWithType.ql @@ -1,7 +1,8 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - -where f.refersTo(o, c, x) and exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) - -select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, c, x) and + exists(CallNode call | call.getFunction().getNode().(Name).getId() = "use" and call.getArg(0) = f) +select f.getLocation().getFile().getShortName(), f.getLocation().getStartLine(), f.toString(), + o.toString(), c.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/import_star/Values.ql b/python/ql/test/library-tests/PointsTo/import_star/Values.ql index f5bfe1bfeac..b54b8c6c78d 100644 --- a/python/ql/test/library-tests/PointsTo/import_star/Values.ql +++ b/python/ql/test/library-tests/PointsTo/import_star/Values.ql @@ -1,7 +1,5 @@ - import python from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) +where f.pointsTo(ctx, v, origin) select f, ctx, v diff --git a/python/ql/test/library-tests/PointsTo/imports/Runtime.ql b/python/ql/test/library-tests/PointsTo/imports/Runtime.ql index 4a25bff744a..4d917aa5af6 100644 --- a/python/ql/test/library-tests/PointsTo/imports/Runtime.ql +++ b/python/ql/test/library-tests/PointsTo/imports/Runtime.ql @@ -1,8 +1,9 @@ - import python from int line, ControlFlowNode f, Object o, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, orig) and line = f.getLocation().getStartLine() and line != 0 +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, orig) and + line = f.getLocation().getStartLine() and + line != 0 select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), orig.toString() diff --git a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql index eca5e965ea8..7e915d04573 100644 --- a/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql +++ b/python/ql/test/library-tests/PointsTo/imports/RuntimeWithType.ql @@ -1,8 +1,10 @@ - import python from int line, ControlFlowNode f, Object o, ClassObject cls, ControlFlowNode orig -where - not f.getLocation().getFile().inStdlib() and - f.refersTo(o, cls, orig) and line = f.getLocation().getStartLine() and line != 0 -select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), cls.toString(), orig.toString() +where + not f.getLocation().getFile().inStdlib() and + f.refersTo(o, cls, orig) and + line = f.getLocation().getStartLine() and + line != 0 +select f.getLocation().getFile().getShortName(), line, f.toString(), o.toString(), cls.toString(), + orig.toString() diff --git a/python/ql/test/library-tests/PointsTo/indexing/Test.ql b/python/ql/test/library-tests/PointsTo/indexing/Test.ql index 70b62e825f7..825cb1cf3be 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/Test.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/Test.ql @@ -1,8 +1,7 @@ import python from ControlFlowNode f, Object o, ControlFlowNode x - -where f.refersTo(o, x) and -f.getLocation().getFile().getBaseName() = "test.py" - +where + f.refersTo(o, x) and + f.getLocation().getFile().getBaseName() = "test.py" select f.getLocation().getStartLine(), f.toString(), o.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql index 6b0c8b8460d..e11999a75de 100644 --- a/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql +++ b/python/ql/test/library-tests/PointsTo/indexing/TestWithType.ql @@ -1,8 +1,8 @@ import python from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - -where f.refersTo(o, c, x) and -f.getLocation().getFile().getBaseName() = "test.py" - -select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), x.getLocation().getStartLine() +where + f.refersTo(o, c, x) and + f.getLocation().getFile().getBaseName() = "test.py" +select f.getLocation().getStartLine(), f.toString(), o.toString(), c.toString(), + x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql index 27b2ed4ce2f..c4677b7df51 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/BaseTypes.ql @@ -1,7 +1,7 @@ - import python from ClassObject cls, ClassObject base, int n -where not cls.isBuiltin() and -base = cls.getBaseType(n) +where + not cls.isBuiltin() and + base = cls.getBaseType(n) select cls.toString(), n, base.toString() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql index d35ac04bb30..f91d207fc70 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Calls.ql @@ -1,8 +1,5 @@ - import python from Call c, FunctionObject f - where f.getACall().getNode() = c - select c.getLocation().getStartLine(), f.toString(), f.getFunction().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql b/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql index aefdb8894bd..def579bb22d 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Declared.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql index ee837e66478..be4d9ef5711 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Declares.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.Base diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql b/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql index bf020de465b..13d3eece75f 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Lookup.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql index 064cc2ca688..3768116ff11 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/MetaClass.ql @@ -1,8 +1,7 @@ - import python from ClassObject cls, ClassObject meta -where not cls.isBuiltin() and -meta = cls.getMetaClass() +where + not cls.isBuiltin() and + meta = cls.getMetaClass() select cls.toString(), meta.toString() - diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql b/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql index 38767957493..7fdd431c216 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Mro.ql @@ -1,14 +1,10 @@ - import python - private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from ClassObjectInternal c diff --git a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql index a72da5f5248..050690fd1cb 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/Self.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/Self.ql @@ -1,4 +1,3 @@ - import python from NameNode n, Object value, ClassObject cls diff --git a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql index 0793957f2e4..7810c607787 100644 --- a/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql +++ b/python/ql/test/library-tests/PointsTo/inheritance/SuperTypes.ql @@ -1,7 +1,7 @@ - import python from ClassObject cls, ClassObject sup -where not cls.isBuiltin() and -sup = cls.getASuperType() +where + not cls.isBuiltin() and + sup = cls.getASuperType() select cls.toString(), sup.toString() diff --git a/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql b/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql index d3cde3b0771..996b8597d5e 100644 --- a/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql +++ b/python/ql/test/library-tests/PointsTo/local/LocalPointsTo.ql @@ -1,10 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ObjectInternal obj, ControlFlowNode orig -where exists(ExprStmt s | s.getValue().getAFlowNode() = f) and -PointsTo::pointsTo(f, _, obj, orig) - +where + exists(ExprStmt s | s.getValue().getAFlowNode() = f) and + PointsTo::pointsTo(f, _, obj, orig) select f, obj.toString(), orig diff --git a/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql b/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql index febbda03f03..67aff9597c2 100644 --- a/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/lookup/Lookup.ql @@ -1,12 +1,13 @@ import python from string l, NameNode n -where n.getLocation().getFile().getShortName() = "test.py" and -( - n.isGlobal() and l = "global" - or - n.isLocal() and l = "local" - or - n.isNonLocal() and l = "non-local" -) +where + n.getLocation().getFile().getShortName() = "test.py" and + ( + n.isGlobal() and l = "global" + or + n.isLocal() and l = "local" + or + n.isNonLocal() and l = "non-local" + ) select n.getLocation().getStartLine(), n.getId(), l diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql index 4fe75b70572..d9cb2f019a6 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Failed.ql @@ -1,9 +1,7 @@ - import python from ClassObject cls, string reason - -where cls.getPyClass().getEnclosingModule().getName() = "test" -and cls.failedInference(reason) - +where + cls.getPyClass().getEnclosingModule().getName() = "test" and + cls.failedInference(reason) select cls, reason diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql b/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql index ec3257a8627..5a10701ef83 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Mro.ql @@ -1,14 +1,10 @@ - import python - private import semmle.python.objects.ObjectInternal private import semmle.python.pointsto.PointsTo /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from PythonClassObjectInternal cls diff --git a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql index 8c5d6913e15..29feef64ec1 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/Style.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/Style.ql @@ -1,13 +1,11 @@ - - import python - from ClassObject cls, string style -where cls.getPyClass().getEnclosingModule().getName() = "test" -and ( - cls.isNewStyle() and style = "new" - or - cls.isOldStyle() and style = "old" -) +where + cls.getPyClass().getEnclosingModule().getName() = "test" and + ( + cls.isNewStyle() and style = "new" + or + cls.isOldStyle() and style = "old" + ) select cls, style diff --git a/python/ql/test/library-tests/PointsTo/metaclass/test.ql b/python/ql/test/library-tests/PointsTo/metaclass/test.ql index 5b80203e60f..17b90483315 100644 --- a/python/ql/test/library-tests/PointsTo/metaclass/test.ql +++ b/python/ql/test/library-tests/PointsTo/metaclass/test.ql @@ -1,12 +1,9 @@ - import python private import semmle.python.objects.ObjectInternal /** Make unknown type visible */ class UnknownType extends UnknownClassInternal { - override string toString() { result = "*UNKNOWN TYPE" } - } from ClassObject cls diff --git a/python/ql/test/library-tests/PointsTo/new/Call.ql b/python/ql/test/library-tests/PointsTo/new/Call.ql index f740b0060f6..f014001f315 100644 --- a/python/ql/test/library-tests/PointsTo/new/Call.ql +++ b/python/ql/test/library-tests/PointsTo/new/Call.ql @@ -1,8 +1,6 @@ - import python import Util from ControlFlowNode call, FunctionObject func - where call = func.getACall() -select locate(call.getLocation(), "abdglq"), call.toString(), func.getQualifiedName() \ No newline at end of file +select locate(call.getLocation(), "abdglq"), call.toString(), func.getQualifiedName() diff --git a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql index 2d13f2ae851..5ad6fabd380 100644 --- a/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql +++ b/python/ql/test/library-tests/PointsTo/new/ClassMethod.ql @@ -1,9 +1,8 @@ - import python import semmle.python.types.Descriptors import Util from ClassMethodObject cm, CallNode call where call = cm.getACall() -select locate(call.getLocation(), "lp"), cm.getFunction().toString(), cm.(ControlFlowNode).getLocation().toString() - +select locate(call.getLocation(), "lp"), cm.getFunction().toString(), + cm.(ControlFlowNode).getLocation().toString() diff --git a/python/ql/test/library-tests/PointsTo/new/Dataflow.ql b/python/ql/test/library-tests/PointsTo/new/Dataflow.ql index c2ed05aa9dc..47a12acee53 100755 --- a/python/ql/test/library-tests/PointsTo/new/Dataflow.ql +++ b/python/ql/test/library-tests/PointsTo/new/Dataflow.ql @@ -1,8 +1,7 @@ - - import python import Util from EssaVariable v, EssaDefinition def where def = v.getDefinition() and not v.getSourceVariable() instanceof SpecialSsaSourceVariable -select locate(def.getLocation(), "abdefghijknrs_"), v.getRepresentation() + " = " + def.getRepresentation() +select locate(def.getLocation(), "abdefghijknrs_"), + v.getRepresentation() + " = " + def.getRepresentation() diff --git a/python/ql/test/library-tests/PointsTo/new/Definitions.ql b/python/ql/test/library-tests/PointsTo/new/Definitions.ql index dbaac3b09f9..5abcb663e16 100644 --- a/python/ql/test/library-tests/PointsTo/new/Definitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/Definitions.ql @@ -1,8 +1,6 @@ - import python - import Util from EssaDefinition def, Variable v where v = def.getSourceVariable() and not v instanceof SpecialSsaSourceVariable -select locate(def.getLocation(), "abdgk"), v.toString(), def.getAQlClass() \ No newline at end of file +select locate(def.getLocation(), "abdgk"), v.toString(), def.getAQlClass() diff --git a/python/ql/test/library-tests/PointsTo/new/Live.ql b/python/ql/test/library-tests/PointsTo/new/Live.ql index 51f2b4e04a7..4bcb7da27e6 100644 --- a/python/ql/test/library-tests/PointsTo/new/Live.ql +++ b/python/ql/test/library-tests/PointsTo/new/Live.ql @@ -1,14 +1,10 @@ - import python import semmle.python.essa.SsaCompute - import Util from Variable var, BasicBlock b, ControlFlowNode loc, string end where -Liveness::liveAtEntry(var, b) and end = "entry" and loc = b.getNode(0) -or -Liveness::liveAtExit(var, b) and end = "exit" and loc = b.getLastNode() - - -select var, locate(loc.getLocation(), "b"), end \ No newline at end of file + Liveness::liveAtEntry(var, b) and end = "entry" and loc = b.getNode(0) + or + Liveness::liveAtExit(var, b) and end = "exit" and loc = b.getLastNode() +select var, locate(loc.getLocation(), "b"), end diff --git a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql index 4e30796dc0b..18fd5e9e37c 100644 --- a/python/ql/test/library-tests/PointsTo/new/NameSpace.ql +++ b/python/ql/test/library-tests/PointsTo/new/NameSpace.ql @@ -2,17 +2,17 @@ import python import Util from Scope s, string name, Object val -where name != "__name__" and -( - exists(ModuleObject m | - m.getModule() = s and - m.attributeRefersTo(name, val, _) - ) - or - exists(ClassObject cls | - cls.getPyClass() = s and - cls.declaredAttribute(name) = val - ) -) - -select locate(s.getLocation(), "abcdghijklopqrs"), s.toString(), name, repr(val) \ No newline at end of file +where + name != "__name__" and + ( + exists(ModuleObject m | + m.getModule() = s and + m.attributeRefersTo(name, val, _) + ) + or + exists(ClassObject cls | + cls.getPyClass() = s and + cls.declaredAttribute(name) = val + ) + ) +select locate(s.getLocation(), "abcdghijklopqrs"), s.toString(), name, repr(val) diff --git a/python/ql/test/library-tests/PointsTo/new/Parameters.ql b/python/ql/test/library-tests/PointsTo/new/Parameters.ql index e3a76f9dc70..50c08a6fa0d 100644 --- a/python/ql/test/library-tests/PointsTo/new/Parameters.ql +++ b/python/ql/test/library-tests/PointsTo/new/Parameters.ql @@ -1,10 +1,6 @@ - import python - import Util from ParameterDefinition param, boolean self -where -if param.isSelf() then self = true else self = false - +where if param.isSelf() then self = true else self = false select locate(param.getLocation(), "g"), param.toString(), self diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql index 341c6f28745..044d33c2887 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToMissing.ql @@ -4,7 +4,6 @@ import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal /* This test should return _no_ results. */ - predicate relevant_node(ControlFlowNode n) { exists(CallNode c | c.getFunction().(NameNode).getId() = "check" and @@ -14,8 +13,8 @@ predicate relevant_node(ControlFlowNode n) { exists(Comment c, string filepath, int bl | n.getNode().getScope().getLocation().hasLocationInfo(filepath, bl, _, _, _) and c.getLocation().hasLocationInfo(filepath, bl, _, _, _) and - c.getText().matches("%check") - and not n.(NameNode).isStore() + c.getText().matches("%check") and + not n.(NameNode).isStore() ) } diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql index 3bebd98bff1..c5009ad4cb6 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToNone.ql @@ -2,8 +2,5 @@ import python import Util from ControlFlowNode f, ControlFlowNode x - -where -f.refersTo(theNoneObject(), _, x) - +where f.refersTo(theNoneObject(), _, x) select locate(f.getLocation(), "abcdghijklmopqr"), f.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql index 9c9c432717f..27ebf200ee2 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToUnknown.ql @@ -4,7 +4,5 @@ import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ControlFlowNode x - where PointsTo::pointsTo(f, _, ObjectInternal::unknown(), x) - select locate(f.getLocation(), "abchr"), f.toString(), x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected index c3a1eebc413..5b452c39073 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.expected @@ -1,4 +1,4 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithContext.ql:8,7-26) +WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithContext.ql:7,7-26) | a_simple.py:2 | ControlFlowNode for FloatLiteral | float 1.0 | builtin-class float | 2 | import | | a_simple.py:2 | ControlFlowNode for f1 | float 1.0 | builtin-class float | 2 | import | | a_simple.py:3 | ControlFlowNode for dict | builtin-class dict | builtin-class type | 3 | import | diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql index e2ef1fc3c61..56a58642f1c 100755 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithContext.ql @@ -4,7 +4,6 @@ import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x, PointsToContext ctx - where PointsTo::points_to(f, ctx, o, c, x) - -select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), repr(o), repr(c), x.getLocation().getStartLine(), ctx +select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), repr(o), repr(c), + x.getLocation().getStartLine(), ctx diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected index 84bf64aacfa..21c14f75a4e 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.expected @@ -1,4 +1,4 @@ -WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithType.ql:7,7-26) +WARNING: Predicate points_to has been deprecated and may be removed in future (PointsToWithType.ql:6,7-26) | a_simple.py:2 | ControlFlowNode for FloatLiteral | float 1.0 | builtin-class float | 2 | | a_simple.py:2 | ControlFlowNode for f1 | float 1.0 | builtin-class float | 2 | | a_simple.py:3 | ControlFlowNode for dict | builtin-class dict | builtin-class type | 3 | diff --git a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql index 0c845f6bc3c..ed04a0b3dc3 100644 --- a/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql +++ b/python/ql/test/library-tests/PointsTo/new/PointsToWithType.ql @@ -3,7 +3,6 @@ import Util import semmle.python.pointsto.PointsTo from ControlFlowNode f, Object o, ClassObject c, ControlFlowNode x - where PointsTo::points_to(f, _, o, c, x) - -select locate(f.getLocation(), "abdeghijkls"), f.toString(), repr(o), repr(c), x.getLocation().getStartLine() +select locate(f.getLocation(), "abdeghijkls"), f.toString(), repr(o), repr(c), + x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/new/Precedes.ql b/python/ql/test/library-tests/PointsTo/new/Precedes.ql index 959ec181f5f..bda245eca6d 100644 --- a/python/ql/test/library-tests/PointsTo/new/Precedes.ql +++ b/python/ql/test/library-tests/PointsTo/new/Precedes.ql @@ -1,8 +1,7 @@ - import python import Util from Scope pre, Scope post where pre.precedes(post) - -select locate(pre.getLocation(), "q"), pre.toString(), locate(post.getLocation(), "q"), post.toString() +select locate(pre.getLocation(), "q"), pre.toString(), locate(post.getLocation(), "q"), + post.toString() diff --git a/python/ql/test/library-tests/PointsTo/new/Reachable.ql b/python/ql/test/library-tests/PointsTo/new/Reachable.ql index 577d724c8e6..f8b2f0585eb 100644 --- a/python/ql/test/library-tests/PointsTo/new/Reachable.ql +++ b/python/ql/test/library-tests/PointsTo/new/Reachable.ql @@ -1,4 +1,3 @@ - import python private import semmle.python.pointsto.PointsTo import Util diff --git a/python/ql/test/library-tests/PointsTo/new/SSA.expected b/python/ql/test/library-tests/PointsTo/new/SSA.expected index d4858045a9f..fb0b2156ecc 100644 --- a/python/ql/test/library-tests/PointsTo/new/SSA.expected +++ b/python/ql/test/library-tests/PointsTo/new/SSA.expected @@ -1,4 +1,4 @@ -WARNING: Predicate ssa_variable_points_to has been deprecated and may be removed in future (SSA.ql:10,1-33) +WARNING: Predicate ssa_variable_points_to has been deprecated and may be removed in future (SSA.ql:10,5-37) | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code' | builtin-class str | | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code.package' | builtin-class str | | __init__.py:0 | __name___0 = ScopeEntryDefinition | 'code.test_package' | builtin-class str | diff --git a/python/ql/test/library-tests/PointsTo/new/SSA.ql b/python/ql/test/library-tests/PointsTo/new/SSA.ql index 6c30a5f031f..6c154f57e57 100644 --- a/python/ql/test/library-tests/PointsTo/new/SSA.ql +++ b/python/ql/test/library-tests/PointsTo/new/SSA.ql @@ -1,11 +1,12 @@ - import python private import semmle.python.pointsto.PointsTo private import semmle.python.pointsto.PointsToContext import Util from EssaVariable v, EssaDefinition def, Object o, ClassObject cls -where def = v.getDefinition() and -not v.getSourceVariable() instanceof SpecialSsaSourceVariable and -PointsTo::ssa_variable_points_to(v, _, o, cls, _) -select locate(def.getLocation(), "abcdegjqmns_"), v.getRepresentation() + " = " + def.getRepresentation(), repr(o), repr(cls) +where + def = v.getDefinition() and + not v.getSourceVariable() instanceof SpecialSsaSourceVariable and + PointsTo::ssa_variable_points_to(v, _, o, cls, _) +select locate(def.getLocation(), "abcdegjqmns_"), + v.getRepresentation() + " = " + def.getRepresentation(), repr(o), repr(cls) diff --git a/python/ql/test/library-tests/PointsTo/new/Sanity.ql b/python/ql/test/library-tests/PointsTo/new/Sanity.ql index 5559354362c..8c3347f6682 100644 --- a/python/ql/test/library-tests/PointsTo/new/Sanity.ql +++ b/python/ql/test/library-tests/PointsTo/new/Sanity.ql @@ -1,98 +1,119 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal predicate ssa_sanity(string clsname, string problem, string what) { /* Exactly one definition of each SSA variable */ - exists(EssaVariable var | - clsname = var.getAQlClass() | + exists(EssaVariable var | clsname = var.getAQlClass() | /* Exactly one definition of each SSA variable */ - count(var.getDefinition()) != 1 and problem = " has " + count(var.getDefinition()) + " definitions." and + count(var.getDefinition()) != 1 and + problem = " has " + count(var.getDefinition()) + " definitions." and what = "SSA variable " + var.getSourceVariable().getName() or /* Backing variable */ - not exists(var.getSourceVariable()) and problem = "An SSA variable has no backing variable." and + not exists(var.getSourceVariable()) and + problem = "An SSA variable has no backing variable." and what = "An SSA variable" or - count(var.getSourceVariable()) != 1 and problem = var.getSourceVariable().getName() + " has " + count(var.getSourceVariable()) + " backing variables." and + count(var.getSourceVariable()) != 1 and + problem = + var.getSourceVariable().getName() + " has " + count(var.getSourceVariable()) + + " backing variables." and what = "SSA variable " + var.getSourceVariable().getName() ) or /* Exactly one location */ exists(EssaDefinition def | clsname = def.getAQlClass() and - what = "SSA Definition " + def.getSourceVariable().getName() + " in " + def.getSourceVariable().(Variable).getScope().getName() and - count(def.getLocation()) != 1 and problem = " has " + count(def.getLocation()) + " locations" + what = + "SSA Definition " + def.getSourceVariable().getName() + " in " + + def.getSourceVariable().(Variable).getScope().getName() and + count(def.getLocation()) != 1 and + problem = " has " + count(def.getLocation()) + " locations" ) or /* Must have a source variable */ exists(EssaDefinition def | clsname = def.getAQlClass() and not exists(def.getSourceVariable()) and - what = " at " + def.getLocation() and + what = " at " + def.getLocation() and problem = "has not source variable" ) - or + or /* Variables must have exactly one representation */ exists(EssaVariable var | clsname = var.getAQlClass() and - what = "SSA variable " + var.getSourceVariable().getName() + " defined at " + var.getDefinition().getLocation() and - count(var.getRepresentation()) != 1 and problem = " has " + count(var.getRepresentation()) + " representations" + what = + "SSA variable " + var.getSourceVariable().getName() + " defined at " + + var.getDefinition().getLocation() and + count(var.getRepresentation()) != 1 and + problem = " has " + count(var.getRepresentation()) + " representations" ) or /* Definitions must have exactly one representation */ exists(EssaDefinition def | clsname = def.getAQlClass() and what = "SSA definition " + def.getSourceVariable().getName() + " at " + def.getLocation() and - count(def.getRepresentation()) != 1 and problem = " has " + count(def.getRepresentation()) + " representations: " + def.getRepresentation() + count(def.getRepresentation()) != 1 and + problem = + " has " + count(def.getRepresentation()) + " representations: " + def.getRepresentation() ) or /* Refinements must have exactly one input */ exists(EssaNodeRefinement ref | clsname = ref.getAQlClass() and what = "Refinement " + ref.getSourceVariable().getName() + " at " + ref.getLocation() and - count(ref.getInput()) != 1 and problem = " has " + count(ref.getInput()) + " inputs: " + ref.getInput().getRepresentation() + count(ref.getInput()) != 1 and + problem = " has " + count(ref.getInput()) + " inputs: " + ref.getInput().getRepresentation() ) or - /* Ideally filter nodes should have exactly one input, but it is not a big deal - * if we prune away the input, leaving it with none. */ + /* + * Ideally filter nodes should have exactly one input, but it is not a big deal + * if we prune away the input, leaving it with none. + */ + exists(EssaEdgeRefinement def | clsname = def.getAQlClass() and - what = def.getSourceVariable().getName() + " at " + def.getLocation() | - count(def.getInput()) > 1 and problem =" has " + count(def.getInput()) + " inputs." + what = def.getSourceVariable().getName() + " at " + def.getLocation() + | + count(def.getInput()) > 1 and problem = " has " + count(def.getInput()) + " inputs." ) or /* Each use has only one reaching SSA variable */ exists(ControlFlowNode use, SsaSourceVariable v, int c | c = strictcount(EssaVariable s | s.getAUse() = use and s.getSourceVariable() = v) and - clsname = use.getAQlClass() and c != 1 and - what = use + " at " + use.getLocation() and - problem =" has " + c + " SSA variables reaching." + clsname = use.getAQlClass() and + c != 1 and + what = use + " at " + use.getLocation() and + problem = " has " + c + " SSA variables reaching." ) or /* Python-specific subclasses of EssaDefinitions should be disjoint and complete */ exists(EssaDefinition def | clsname = def.getAQlClass() and - what = def.getVariable().getName() + " at " + def.getLocation() and - problem = "has non-disjoint subclasses" | - strictcount(def.getAQlClass()) > 2 or + what = def.getVariable().getName() + " at " + def.getLocation() and + problem = "has non-disjoint subclasses" + | + strictcount(def.getAQlClass()) > 2 + or /* OK if method call and argument overlap: `x.foo(x)` */ strictcount(def.getAQlClass()) > 1 and - not clsname = "ArgumentRefinement" and not clsname = "SelfCallsiteRefinement" + not clsname = "ArgumentRefinement" and + not clsname = "SelfCallsiteRefinement" ) or exists(EssaDefinition def | clsname = def.getAQlClass() and clsname.prefix(4) = "Essa" and - what = " at " + def.getLocation() and + what = " at " + def.getLocation() and problem = "not covered by Python-specific subclass." ) or // All modules should have __name__ exists(Module m | - what = " at " + m.getLocation() and - clsname = "Module" | + what = " at " + m.getLocation() and + clsname = "Module" + | not exists(m.getName()) and problem = "does not have a name" or @@ -113,7 +134,8 @@ predicate undefined_sanity(string clsname, string problem, string what) { /* Variables may be undefined, but values cannot be */ exists(ControlFlowNode f | PointsToInternal::pointsTo(f, _, ObjectInternal::undefined(), _) and - clsname = f.getAQlClass() and not clsname = "AnyNode" and + clsname = f.getAQlClass() and + not clsname = "AnyNode" and problem = " points-to an undefined variable" and what = f.toString() ) @@ -122,4 +144,3 @@ predicate undefined_sanity(string clsname, string problem, string what) { from string clsname, string problem, string what where ssa_sanity(clsname, problem, what) or undefined_sanity(clsname, problem, what) select clsname, what, problem - diff --git a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql index 08928b0c9f0..8cf0b4c15a6 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceEdgeDefinitions.ql @@ -1,7 +1,5 @@ - import python import semmle.python.pointsto.PointsTo - import Util from SsaSourceVariable var, ControlFlowNode use, BasicBlock pred diff --git a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql index 53e5d69953e..a1547da65c6 100644 --- a/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql +++ b/python/ql/test/library-tests/PointsTo/new/SourceNodeDefinitions.ql @@ -1,14 +1,13 @@ - import python import semmle.python.pointsto.PointsTo - import Util from SsaSourceVariable var, ControlFlowNode defn, string kind -where not var instanceof SpecialSsaSourceVariable and -( - var.hasDefiningNode(defn) and kind = "definition" - or - var.hasRefinement(_, defn) and kind = "refinement" -) +where + not var instanceof SpecialSsaSourceVariable and + ( + var.hasDefiningNode(defn) and kind = "definition" + or + var.hasRefinement(_, defn) and kind = "refinement" + ) select locate(defn.getLocation(), "ab"), var.(Variable), defn.toString(), kind diff --git a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql index 4a4d83160c3..dc71ac5df65 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaAttr.ql @@ -1,12 +1,11 @@ - import python private import semmle.python.pointsto.PointsTo private import semmle.python.objects.ObjectInternal import Util from EssaVariable var, string name, ObjectInternal o, Context ctx -where AttributePointsTo::variableAttributePointsTo(var, ctx, name, o, _) and not var.getSourceVariable() instanceof SpecialSsaSourceVariable -select -locate(var.getDefinition().getLocation(), "abdfgikm"), var.getRepresentation(), -name, var.getDefinition().getRepresentation(), o, ctx - +where + AttributePointsTo::variableAttributePointsTo(var, ctx, name, o, _) and + not var.getSourceVariable() instanceof SpecialSsaSourceVariable +select locate(var.getDefinition().getLocation(), "abdfgikm"), var.getRepresentation(), name, + var.getDefinition().getRepresentation(), o, ctx diff --git a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql index 9c01da90a59..2a8e8f1e750 100644 --- a/python/ql/test/library-tests/PointsTo/new/SsaUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/SsaUses.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import Util diff --git a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql index 0a17a3e118a..2367df63b63 100644 --- a/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql +++ b/python/ql/test/library-tests/PointsTo/new/TestEvaluate.ql @@ -1,19 +1,19 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import Util - -from ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx, ControlFlowNode origin, string what -where -not use instanceof NameConstantNode and -not use.getNode() instanceof ImmutableLiteral and -eval = Conditionals::testEvaluates(test, use, ctx, val, origin) and -( - what = val.getSource().(Object).toString() - or - not exists(val.getSource()) and what = origin.getNode().toString() -) -select locate(test.getLocation(), "bc"), test.getNode().toString(), eval.toString(), use.getNode().toString(), what - +from + ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx, + ControlFlowNode origin, string what +where + not use instanceof NameConstantNode and + not use.getNode() instanceof ImmutableLiteral and + eval = Conditionals::testEvaluates(test, use, ctx, val, origin) and + ( + what = val.getSource().(Object).toString() + or + not exists(val.getSource()) and what = origin.getNode().toString() + ) +select locate(test.getLocation(), "bc"), test.getNode().toString(), eval.toString(), + use.getNode().toString(), what diff --git a/python/ql/test/library-tests/PointsTo/new/Util.qll b/python/ql/test/library-tests/PointsTo/new/Util.qll index af8645f8d94..f59a1a8dae1 100644 --- a/python/ql/test/library-tests/PointsTo/new/Util.qll +++ b/python/ql/test/library-tests/PointsTo/new/Util.qll @@ -13,12 +13,17 @@ string locate(Location l, string which) { } string repr(Object o) { - /* Do not show `unknownValue()` to keep noise levels down. + /* + * Do not show `unknownValue()` to keep noise levels down. * To show it add: * `o = unknownValue() and result = "*UNKNOWN VALUE*"` */ - not o instanceof StringObject and not o = undefinedVariable() and not o = theUnknownType() and - not o = theBoundMethodType() and result = o.toString() + + not o instanceof StringObject and + not o = undefinedVariable() and + not o = theUnknownType() and + not o = theBoundMethodType() and + result = o.toString() or o = undefinedVariable() and result = "*UNDEFINED*" or @@ -30,16 +35,15 @@ string repr(Object o) { o = theBoundMethodType() and result = "builtin-class method" } -predicate long_tuple(Value v) { - v.(TupleObjectInternal).length() > 3 -} +predicate long_tuple(Value v) { v.(TupleObjectInternal).length() > 3 } string vrepr(Value v) { /* Work around differing names in 2/3 */ not v = ObjectInternal::boundMethod() and - not long_tuple(v) and result = v.toString() + not long_tuple(v) and + result = v.toString() or v = ObjectInternal::boundMethod() and result = "builtin-class method" or long_tuple(v) and result = "(..., ...)" -} \ No newline at end of file +} diff --git a/python/ql/test/library-tests/PointsTo/new/Values.ql b/python/ql/test/library-tests/PointsTo/new/Values.ql index 8e6bd9c9f00..754fcfede54 100644 --- a/python/ql/test/library-tests/PointsTo/new/Values.ql +++ b/python/ql/test/library-tests/PointsTo/new/Values.ql @@ -1,9 +1,7 @@ - import python import Util - from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) -select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) +where f.pointsTo(ctx, v, origin) +select locate(f.getLocation(), "abeghijklmnpqrstu"), f.toString(), ctx, vrepr(v), + vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/new/VarUses.ql b/python/ql/test/library-tests/PointsTo/new/VarUses.ql index a8ef096821e..56c1ca637a1 100644 --- a/python/ql/test/library-tests/PointsTo/new/VarUses.ql +++ b/python/ql/test/library-tests/PointsTo/new/VarUses.ql @@ -1,8 +1,9 @@ - import python import semmle.python.pointsto.PointsTo import Util from SsaSourceVariable var, ControlFlowNode use -where (use = var.getAUse() or var.hasRefinement(use, _)) and not var instanceof SpecialSsaSourceVariable +where + (use = var.getAUse() or var.hasRefinement(use, _)) and + not var instanceof SpecialSsaSourceVariable select locate(use.getLocation(), "abd"), var.getName(), use.toString() diff --git a/python/ql/test/library-tests/PointsTo/properties/Lookup.ql b/python/ql/test/library-tests/PointsTo/properties/Lookup.ql index 10c32412d85..d7820250723 100644 --- a/python/ql/test/library-tests/PointsTo/properties/Lookup.ql +++ b/python/ql/test/library-tests/PointsTo/properties/Lookup.ql @@ -1,4 +1,3 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal diff --git a/python/ql/test/library-tests/PointsTo/properties/Values.ql b/python/ql/test/library-tests/PointsTo/properties/Values.ql index 0173d7d6219..597a54cb641 100644 --- a/python/ql/test/library-tests/PointsTo/properties/Values.ql +++ b/python/ql/test/library-tests/PointsTo/properties/Values.ql @@ -1,4 +1,3 @@ - import python import semmle.python.objects.ObjectInternal @@ -10,6 +9,5 @@ string vrepr(Value v) { } from ControlFlowNode f, Context ctx, Value v, ControlFlowNode origin -where - f.pointsTo(ctx, v, origin) +where f.pointsTo(ctx, v, origin) select f.getLocation(), f.toString(), ctx, vrepr(v), vrepr(v.getClass()) diff --git a/python/ql/test/library-tests/PointsTo/returns/Test.ql b/python/ql/test/library-tests/PointsTo/returns/Test.ql index a30d0ef1c76..8546de90f24 100644 --- a/python/ql/test/library-tests/PointsTo/returns/Test.ql +++ b/python/ql/test/library-tests/PointsTo/returns/Test.ql @@ -1,4 +1,4 @@ import python from PyFunctionObject f -select f.toString(), f.getAnInferredReturnType().toString() \ No newline at end of file +select f.toString(), f.getAnInferredReturnType().toString() diff --git a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql index b164406276e..a82002b1d5f 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/Checks.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/Checks.ql @@ -1,7 +1,6 @@ - import python import semmle.python.pointsto.PointsTo -from Value sup, Value cls +from Value sup, Value cls where Expressions::requireSubClass(cls, sup) select cls, sup diff --git a/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql b/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql index fd32bfcbe64..0f197edeb0a 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/TestEvaluate.ql @@ -1,12 +1,12 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal import semmle.python.pointsto.PointsToContext - -from ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx +from + ControlFlowNode test, ControlFlowNode use, ObjectInternal val, boolean eval, PointsToContext ctx where -PointsTo::pointsTo(use, ctx, val, _) and -eval = Conditionals::testEvaluates(test, use, ctx, val, _) -select test.getLocation().getStartLine(), test.getNode().toString(), eval.toString(), use.getNode().toString(), val.toString() + PointsTo::pointsTo(use, ctx, val, _) and + eval = Conditionals::testEvaluates(test, use, ctx, val, _) +select test.getLocation().getStartLine(), test.getNode().toString(), eval.toString(), + use.getNode().toString(), val.toString() diff --git a/python/ql/test/library-tests/PointsTo/subclass/Values.ql b/python/ql/test/library-tests/PointsTo/subclass/Values.ql index 3246ef02764..c50e25c5f36 100644 --- a/python/ql/test/library-tests/PointsTo/subclass/Values.ql +++ b/python/ql/test/library-tests/PointsTo/subclass/Values.ql @@ -1,10 +1,7 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.objects.ObjectInternal from ControlFlowNode f, ObjectInternal v, ControlFlowNode x - where PointsTo::pointsTo(f, _, v, x) - select f.getLocation().getStartLine(), f.toString(), v, x.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql index f21b102338f..6245b56f711 100644 --- a/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql +++ b/python/ql/test/library-tests/PointsTo/super/SuperMethodCall.ql @@ -1,10 +1,11 @@ - import python import semmle.python.pointsto.PointsTo import semmle.python.pointsto.PointsToContext import semmle.python.objects.ObjectInternal from CallNode call, SuperInstance sup, BoundMethodObjectInternal bm -where call.getFunction().inferredValue() = bm and -call.getFunction().(AttrNode).getObject().inferredValue() = sup -select call.getLocation().getStartLine(), call.toString(), bm.getFunction().getSource().(FunctionObject).getQualifiedName() \ No newline at end of file +where + call.getFunction().inferredValue() = bm and + call.getFunction().(AttrNode).getObject().inferredValue() = sup +select call.getLocation().getStartLine(), call.toString(), + bm.getFunction().getSource().(FunctionObject).getQualifiedName() diff --git a/python/ql/test/library-tests/attributes/SelfAttribute.ql b/python/ql/test/library-tests/attributes/SelfAttribute.ql index 0ccfe5a397c..7ac995d2061 100644 --- a/python/ql/test/library-tests/attributes/SelfAttribute.ql +++ b/python/ql/test/library-tests/attributes/SelfAttribute.ql @@ -1,11 +1,9 @@ - import python import semmle.python.SelfAttribute from SelfAttributeRead sa, int line, string g, string l where -line = sa.getLocation().getStartLine() and -if sa.guardedByHasattr() then g = "guarded" else g = "" and - -if sa.locallyDefined() then l = "defined" else l = "" + line = sa.getLocation().getStartLine() and + (if sa.guardedByHasattr() then g = "guarded" else g = "") and + if sa.locallyDefined() then l = "defined" else l = "" select line, sa.getName(), g + l diff --git a/python/ql/test/library-tests/classes/abstract/Abstract.ql b/python/ql/test/library-tests/classes/abstract/Abstract.ql index 1117bc95790..6773bb22785 100644 --- a/python/ql/test/library-tests/classes/abstract/Abstract.ql +++ b/python/ql/test/library-tests/classes/abstract/Abstract.ql @@ -1,12 +1,7 @@ - import python from ClassObject cls, string abstract where -not cls.isBuiltin() and -if cls.isAbstract() then - abstract = "yes" -else - abstract = "no" - + not cls.isBuiltin() and + if cls.isAbstract() then abstract = "yes" else abstract = "no" select cls.toString(), abstract diff --git a/python/ql/test/library-tests/classes/attr/class_attr.ql b/python/ql/test/library-tests/classes/attr/class_attr.ql index 0b283debd5d..3b7bf8b3ba0 100644 --- a/python/ql/test/library-tests/classes/attr/class_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") -select line, cls.toString(), name, obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") +select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql index 843b1ed2b3a..ec798dcf190 100644 --- a/python/ql/test/library-tests/classes/attr/class_defined_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defined_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.declaredAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.declaredAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name, obj.toString() diff --git a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql index e9cfdee5ccd..858d3e49e20 100644 --- a/python/ql/test/library-tests/classes/attr/class_defines_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_defines_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.declaresAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.declaresAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/library-tests/classes/attr/class_has_attr.ql b/python/ql/test/library-tests/classes/attr/class_has_attr.ql index a274a1dd95b..2f16aa4ca97 100644 --- a/python/ql/test/library-tests/classes/attr/class_has_attr.ql +++ b/python/ql/test/library-tests/classes/attr/class_has_attr.ql @@ -7,7 +7,9 @@ import python from ClassObject cls, int line, string name -where cls.hasLocationInfo(_, line, _, _, _) -and cls.hasAttribute(name) and -not cls.isC() and not name.matches("\\_\\_%\\_\\_") +where + cls.hasLocationInfo(_, line, _, _, _) and + cls.hasAttribute(name) and + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") select line, cls.toString(), name diff --git a/python/ql/test/library-tests/classes/attr/hash.ql b/python/ql/test/library-tests/classes/attr/hash.ql index b4485634cce..a8ccf6c9d6b 100644 --- a/python/ql/test/library-tests/classes/attr/hash.ql +++ b/python/ql/test/library-tests/classes/attr/hash.ql @@ -7,9 +7,10 @@ import python from ClassObject cls, int line, Object obj -where cls.hasLocationInfo(_, line, _, _, _) -and obj = cls.lookupAttribute("__hash__") and -not cls.isC() and -not obj = theObjectType().lookupAttribute("__hash__") and -not obj = theTypeType().lookupAttribute("__hash__") -select line, cls.toString(), obj.toString() \ No newline at end of file +where + cls.hasLocationInfo(_, line, _, _, _) and + obj = cls.lookupAttribute("__hash__") and + not cls.isC() and + not obj = theObjectType().lookupAttribute("__hash__") and + not obj = theTypeType().lookupAttribute("__hash__") +select line, cls.toString(), obj.toString() diff --git a/python/ql/test/library-tests/classes/mro/C3.ql b/python/ql/test/library-tests/classes/mro/C3.ql index e433971f1eb..981a55893c2 100644 --- a/python/ql/test/library-tests/classes/mro/C3.ql +++ b/python/ql/test/library-tests/classes/mro/C3.ql @@ -1,9 +1,6 @@ - import python import semmle.python.pointsto.MRO from ClassValue cls where not cls.isBuiltin() - select cls.toString(), Mro::newStyleMro(cls) - diff --git a/python/ql/test/library-tests/comments/blocks.ql b/python/ql/test/library-tests/comments/blocks.ql index 3fbb6946c02..ac306cb3f44 100644 --- a/python/ql/test/library-tests/comments/blocks.ql +++ b/python/ql/test/library-tests/comments/blocks.ql @@ -10,4 +10,4 @@ import Lexical.CommentedOutCode from CommentedOutCodeBlock c, int bl, int el where c.hasLocationInfo(_, bl, _, el, _) -select bl, el, c.toString() \ No newline at end of file +select bl, el, c.toString() diff --git a/python/ql/test/library-tests/comments/blocks_not_example.ql b/python/ql/test/library-tests/comments/blocks_not_example.ql index ccc8c0ba50b..19ed6283a3e 100644 --- a/python/ql/test/library-tests/comments/blocks_not_example.ql +++ b/python/ql/test/library-tests/comments/blocks_not_example.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeBlock c, int bl, int el where c.hasLocationInfo(_, bl, _, el, _) and not c.maybeExampleCode() -select bl, el, c.toString() \ No newline at end of file +select bl, el, c.toString() diff --git a/python/ql/test/library-tests/comments/length.ql b/python/ql/test/library-tests/comments/length.ql index 53d514e6b33..0a15328c35e 100644 --- a/python/ql/test/library-tests/comments/length.ql +++ b/python/ql/test/library-tests/comments/length.ql @@ -1,8 +1,8 @@ - import python import Lexical.CommentedOutCode from CommentBlock block, int line, boolean code -where block.hasLocationInfo(_, line, _, _, _) and -if block instanceof CommentedOutCodeBlock then code = true else code = false +where + block.hasLocationInfo(_, line, _, _, _) and + if block instanceof CommentedOutCodeBlock then code = true else code = false select line, block.length(), code diff --git a/python/ql/test/library-tests/comments/lines.ql b/python/ql/test/library-tests/comments/lines.ql index a07d2ac1953..d71eb039129 100644 --- a/python/ql/test/library-tests/comments/lines.ql +++ b/python/ql/test/library-tests/comments/lines.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeLine c, int l where l = c.getLocation().getStartLine() -select l, c.toString() \ No newline at end of file +select l, c.toString() diff --git a/python/ql/test/library-tests/comments/lines_not_example.ql b/python/ql/test/library-tests/comments/lines_not_example.ql index e6fcaab9d93..2fa0dec3a4e 100644 --- a/python/ql/test/library-tests/comments/lines_not_example.ql +++ b/python/ql/test/library-tests/comments/lines_not_example.ql @@ -1,7 +1,6 @@ - import python import Lexical.CommentedOutCode from CommentedOutCodeLine c, int l where l = c.getLocation().getStartLine() and not c.maybeExampleCode() -select l, c.toString() \ No newline at end of file +select l, c.toString() diff --git a/python/ql/test/library-tests/comments/type_hint.ql b/python/ql/test/library-tests/comments/type_hint.ql index 55ec57c0d5b..26511a2d97f 100644 --- a/python/ql/test/library-tests/comments/type_hint.ql +++ b/python/ql/test/library-tests/comments/type_hint.ql @@ -1,6 +1,4 @@ - import python from TypeHintComment c select c.getLocation().toString(), c.getText() - diff --git a/python/ql/test/library-tests/comparisons/Compare.ql b/python/ql/test/library-tests/comparisons/Compare.ql index 84d97bbbbe2..558da6fc6d7 100644 --- a/python/ql/test/library-tests/comparisons/Compare.ql +++ b/python/ql/test/library-tests/comparisons/Compare.ql @@ -1,9 +1,6 @@ - import python - import semmle.python.Comparisons from Comparison c, ControlFlowNode l, CompareOp op, float k -where -c.tests(l, op, k) +where c.tests(l, op, k) select c.getLocation().getStartLine(), l + " " + op.repr() + " " + k diff --git a/python/ql/test/library-tests/comparisons/Compare2.ql b/python/ql/test/library-tests/comparisons/Compare2.ql index 70d954a4b0e..ade279c9efd 100644 --- a/python/ql/test/library-tests/comparisons/Compare2.ql +++ b/python/ql/test/library-tests/comparisons/Compare2.ql @@ -1,11 +1,12 @@ - import python - import semmle.python.Comparisons from Comparison c, NameNode l, CompareOp op, NameNode r, float k, string add -where -c.tests(l, op, r, k) -and -(k < 0 and add = "" or k >= 0 and add = "+") +where + c.tests(l, op, r, k) and + ( + k < 0 and add = "" + or + k >= 0 and add = "+" + ) select c.getLocation().getStartLine(), l.getId() + " " + op.repr() + " " + r.getId() + add + k diff --git a/python/ql/test/library-tests/comparisons/CompareControls.ql b/python/ql/test/library-tests/comparisons/CompareControls.ql index 01b35c0ffad..b803e40dfed 100644 --- a/python/ql/test/library-tests/comparisons/CompareControls.ql +++ b/python/ql/test/library-tests/comparisons/CompareControls.ql @@ -1,10 +1,7 @@ - import python - import semmle.python.Comparisons from ComparisonControlBlock comp, SsaVariable v, CompareOp op, float k, BasicBlock b -where -comp.controls(v.getAUse(), op, k, b) - -select comp.getTest().getLocation().getStartLine(), v.getId() + " " + op.repr() + " " + k, b.getNode(0).getLocation().getStartLine() +where comp.controls(v.getAUse(), op, k, b) +select comp.getTest().getLocation().getStartLine(), v.getId() + " " + op.repr() + " " + k, + b.getNode(0).getLocation().getStartLine() diff --git a/python/ql/test/library-tests/comparisons/Implication.ql b/python/ql/test/library-tests/comparisons/Implication.ql index f24d1d42234..f94d8ba184a 100644 --- a/python/ql/test/library-tests/comparisons/Implication.ql +++ b/python/ql/test/library-tests/comparisons/Implication.ql @@ -1,9 +1,6 @@ - import python import semmle.python.Comparisons from Comparison a, Comparison that, boolean thisIsTrue, boolean thatIsTrue - where a.impliesThat(thisIsTrue, that, thatIsTrue) - -select a.getLocation().getStartLine(), thisIsTrue, that.getLocation().getStartLine(), thatIsTrue \ No newline at end of file +select a.getLocation().getStartLine(), thisIsTrue, that.getLocation().getStartLine(), thatIsTrue diff --git a/python/ql/test/library-tests/comprehensions/Flow.ql b/python/ql/test/library-tests/comprehensions/Flow.ql index e19d4d75abe..5fd3a0cc61c 100644 --- a/python/ql/test/library-tests/comprehensions/Flow.ql +++ b/python/ql/test/library-tests/comprehensions/Flow.ql @@ -2,4 +2,4 @@ import python from ControlFlowNode p, ControlFlowNode s where p.getASuccessor() = s -select p.getLocation().getStartLine(), p.toString(), s.getLocation().getStartLine(), s.toString() \ No newline at end of file +select p.getLocation().getStartLine(), p.toString(), s.getLocation().getStartLine(), s.toString() diff --git a/python/ql/test/library-tests/dependencies/Dependencies.ql b/python/ql/test/library-tests/dependencies/Dependencies.ql index b5bedbe7b3c..cab84c4417b 100644 --- a/python/ql/test/library-tests/dependencies/Dependencies.ql +++ b/python/ql/test/library-tests/dependencies/Dependencies.ql @@ -1,8 +1,7 @@ - import python import semmle.python.dependencies.Dependencies from DependencyKind dk, AstNode src, Object target where dk.isADependency(src, target) -select dk.toString(), src.getLocation().getFile().getShortName(), src.getLocation().getStartLine(), src.toString(), target.toString() - +select dk.toString(), src.getLocation().getFile().getShortName(), src.getLocation().getStartLine(), + src.toString(), target.toString() diff --git a/python/ql/test/library-tests/descriptors/Descriptors.ql b/python/ql/test/library-tests/descriptors/Descriptors.ql index 658091bfe4e..dd97b623f7f 100644 --- a/python/ql/test/library-tests/descriptors/Descriptors.ql +++ b/python/ql/test/library-tests/descriptors/Descriptors.ql @@ -1,13 +1,9 @@ - import python from ClassObject cls, string kind -where cls.isDescriptorType() and -/* Exclude bound-method as its name differs between 2 and 3 */ -not cls = theBoundMethodType() and -(if cls.isOverridingDescriptorType() then - kind = "overriding" - else - kind = "non-overriding" -) -select cls.toString(), kind \ No newline at end of file +where + cls.isDescriptorType() and + /* Exclude bound-method as its name differs between 2 and 3 */ + not cls = theBoundMethodType() and + (if cls.isOverridingDescriptorType() then kind = "overriding" else kind = "non-overriding") +select cls.toString(), kind diff --git a/python/ql/test/library-tests/descriptors/Methods.ql b/python/ql/test/library-tests/descriptors/Methods.ql index 75d3092198d..4a2ec39d70c 100644 --- a/python/ql/test/library-tests/descriptors/Methods.ql +++ b/python/ql/test/library-tests/descriptors/Methods.ql @@ -1,15 +1,11 @@ - import python import semmle.python.types.Descriptors -int lineof(Object o) { - result = o.getOrigin().getLocation().getStartLine() -} +int lineof(Object o) { result = o.getOrigin().getLocation().getStartLine() } from Object m, FunctionObject f -where - m.(ClassMethodObject).getFunction() = f - or - m.(StaticMethodObject).getFunction() = f +where + m.(ClassMethodObject).getFunction() = f + or + m.(StaticMethodObject).getFunction() = f select lineof(m), m.toString(), lineof(f), f.toString() - diff --git a/python/ql/test/library-tests/encoding/CheckEncoding.ql b/python/ql/test/library-tests/encoding/CheckEncoding.ql index 88e8a580027..60fc167e293 100644 --- a/python/ql/test/library-tests/encoding/CheckEncoding.ql +++ b/python/ql/test/library-tests/encoding/CheckEncoding.ql @@ -2,7 +2,7 @@ import python from File f, string encoding where -encoding = f.getSpecifiedEncoding() -or -not exists(f.getSpecifiedEncoding()) and encoding = "none" + encoding = f.getSpecifiedEncoding() + or + not exists(f.getSpecifiedEncoding()) and encoding = "none" select f.getAbsolutePath(), encoding diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected new file mode 100644 index 00000000000..22c6f68f1d7 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.expected @@ -0,0 +1,23 @@ +| MySanitizerHandlingNot | externally controlled string | test.py:13 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:18 | Pi(s_5) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:28 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:34 | Pi(s_10) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:40 | Pi(s_12) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:50 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:56 | Pi(s_10) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:62 | Pi(s_12) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:76 | Pi(s_3) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:82 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:87 | Pi(s_5) [false] | +| MySanitizerHandlingNot | externally controlled string | test.py:97 | Pi(s_0) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:102 | Pi(s_7) [true] | +| MySanitizerHandlingNot | externally controlled string | test.py:107 | Pi(s_12) [true] | +| MySimpleSanitizer | externally controlled string | test.py:13 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:28 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:34 | Pi(s_10) [true] | +| MySimpleSanitizer | externally controlled string | test.py:50 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:56 | Pi(s_10) [true] | +| MySimpleSanitizer | externally controlled string | test.py:76 | Pi(s_3) [true] | +| MySimpleSanitizer | externally controlled string | test.py:97 | Pi(s_0) [true] | +| MySimpleSanitizer | externally controlled string | test.py:102 | Pi(s_7) [true] | +| MySimpleSanitizer | externally controlled string | test.py:107 | Pi(s_12) [true] | diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql new file mode 100644 index 00000000000..d523f79a963 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/SanitizedEdges.ql @@ -0,0 +1,6 @@ +import python +import Taint + +from Sanitizer s, TaintKind taint, PyEdgeRefinement test +where s.sanitizingEdge(taint, test) +select s, taint, test.getTest().getLocation().toString(), test.getRepresentation() diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll new file mode 100644 index 00000000000..9b2216dbcd9 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/Taint.qll @@ -0,0 +1,76 @@ +import python +import semmle.python.security.TaintTracking +import semmle.python.security.strings.Untrusted + +class SimpleSource extends TaintSource { + SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } + + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + + override string toString() { result = "taint source" } +} + +class MySimpleSanitizer extends Sanitizer { + MySimpleSanitizer() { this = "MySimpleSanitizer" } + + /** + * The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. + * + * Can't handle `if not is_safe(arg):` :\ that's why it's called MySimpleSanitizer + */ + override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { + taint instanceof ExternalStringKind and + exists(CallNode call | test.getTest() = call and test.getSense() = true | + call = Value::named("test.is_safe").getACall() and + test.getInput().getAUse() = call.getAnArg() + ) + } +} + +class MySanitizerHandlingNot extends Sanitizer { + MySanitizerHandlingNot() { this = "MySanitizerHandlingNot" } + + /** The test `if is_safe(arg):` sanitizes `arg` on its `true` edge. */ + override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) { + taint instanceof ExternalStringKind and + clears_taint_on_true(test.getTest(), test.getSense(), test) + } +} + +/** + * Helper predicate that recurses into any nesting of `not` + * + * To reduce the number of tuples this predicate holds for, we include the `PyEdgeRefinement` and + * ensure that `test` is a part of this `PyEdgeRefinement` (instead of just taking the + * `edge_refinement.getInput().getAUse()` part as a part of the predicate). Without including + * `PyEdgeRefinement` as an argument *any* `CallNode c` to `test.is_safe` would be a result of + * this predicate, since the tuple where `test = c` and `sense = true` would hold. + */ +private predicate clears_taint_on_true( + ControlFlowNode test, boolean sense, PyEdgeRefinement edge_refinement +) { + edge_refinement.getTest().getNode().(Expr).getASubExpression*() = test.getNode() and + ( + test = Value::named("test.is_safe").getACall() and + edge_refinement.getInput().getAUse() = test.(CallNode).getAnArg() and + sense = true + or + test.(UnaryExprNode).getNode().getOp() instanceof Not and + exists(ControlFlowNode nested_test | + nested_test = test.(UnaryExprNode).getOperand() and + clears_taint_on_true(nested_test, sense.booleanNot(), edge_refinement) + ) + ) +} + +class TestConfig extends TaintTracking::Configuration { + TestConfig() { this = "TestConfig" } + + override predicate isSanitizer(Sanitizer sanitizer) { + sanitizer instanceof MySanitizerHandlingNot + } + + override predicate isSource(TaintTracking::Source source) { source instanceof SimpleSource } + + override predicate isSink(TaintTracking::Sink sink) { none() } +} diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected new file mode 100644 index 00000000000..269eb47a37f --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.expected @@ -0,0 +1,28 @@ +| test.py:14 | test_basic | s | | ok | +| test.py:16 | test_basic | s | externally controlled string | ok | +| test.py:19 | test_basic | s | externally controlled string | ok | +| test.py:21 | test_basic | s | | ok | +| test.py:29 | test_or | s | externally controlled string | ok | +| test.py:31 | test_or | s | externally controlled string | ok | +| test.py:35 | test_or | s | externally controlled string | ok | +| test.py:37 | test_or | s | externally controlled string | ok | +| test.py:41 | test_or | s | externally controlled string | ok | +| test.py:43 | test_or | s | externally controlled string | ok | +| test.py:51 | test_and | s | | ok | +| test.py:53 | test_and | s | externally controlled string | ok | +| test.py:57 | test_and | s | externally controlled string | ok | +| test.py:59 | test_and | s | | ok | +| test.py:63 | test_and | s | externally controlled string | ok | +| test.py:65 | test_and | s | | ok | +| test.py:73 | test_tricky | s | externally controlled string | failure | +| test.py:77 | test_tricky | s_ | externally controlled string | failure | +| test.py:83 | test_nesting_not | s | | ok | +| test.py:85 | test_nesting_not | s | externally controlled string | ok | +| test.py:88 | test_nesting_not | s | externally controlled string | ok | +| test.py:90 | test_nesting_not | s | | ok | +| test.py:98 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:100 | test_nesting_not_with_and_true | s | | ok | +| test.py:103 | test_nesting_not_with_and_true | s | | ok | +| test.py:105 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:108 | test_nesting_not_with_and_true | s | externally controlled string | ok | +| test.py:110 | test_nesting_not_with_and_true | s | | ok | diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql new file mode 100644 index 00000000000..4df37b9cdfa --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/TestTaint.ql @@ -0,0 +1,31 @@ +import python +import semmle.python.security.TaintTracking +import Taint + +from + Call call, Expr arg, boolean expected_taint, boolean has_taint, string test_res, + string taint_string +where + call.getLocation().getFile().getShortName() = "test.py" and + ( + call.getFunc().(Name).getId() = "ensure_tainted" and + expected_taint = true + or + call.getFunc().(Name).getId() = "ensure_not_tainted" and + expected_taint = false + ) and + arg = call.getAnArg() and + ( + not exists(TaintedNode tainted | tainted.getAstNode() = arg) and + taint_string = "" and + has_taint = false + or + exists(TaintedNode tainted | tainted.getAstNode() = arg | + taint_string = tainted.getTaintKind().toString() + ) and + has_taint = true + ) and + if expected_taint = has_taint then test_res = "ok" else test_res = "failure" +// if expected_taint = has_taint then test_res = "✓" else test_res = "✕" +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string, test_res diff --git a/python/ql/test/library-tests/examples/custom-sanitizer/test.py b/python/ql/test/library-tests/examples/custom-sanitizer/test.py new file mode 100644 index 00000000000..e0bf29f4ee6 --- /dev/null +++ b/python/ql/test/library-tests/examples/custom-sanitizer/test.py @@ -0,0 +1,110 @@ +def random_choice(): + return bool(GLOBAL_UNKOWN_VAR) + +def is_safe(arg): + return UNKNOWN_FUNC(arg) + +def true_func(): + return True + +def test_basic(): + s = TAINTED_STRING + + if is_safe(s): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not is_safe(s): + ensure_tainted(s) + else: + ensure_not_tainted(s) + + +def test_or(): + s = TAINTED_STRING + + # x or y + if is_safe(s) or random_choice(): + ensure_tainted(s) # might be tainted + else: + ensure_tainted(s) # must be tainted + + # not (x or y) + if not(is_safe(s) or random_choice()): + ensure_tainted(s) # must be tainted + else: + ensure_tainted(s) # might be tainted + + # not (x or y) == not x and not y [de Morgan's laws] + if not is_safe(s) and not random_choice(): + ensure_tainted(s) # must be tainted + else: + ensure_tainted(s) # might be tainted + + +def test_and(): + s = TAINTED_STRING + + # x and y + if is_safe(s) and random_choice(): + ensure_not_tainted(s) # must not be tainted + else: + ensure_tainted(s) # might be tainted + + # not (x and y) + if not(is_safe(s) and random_choice()): + ensure_tainted(s) # might be tainted + else: + ensure_not_tainted(s) + + # not (x and y) == not x or not y [de Morgan's laws] + if not is_safe(s) or not random_choice(): + ensure_tainted(s) # might be tainted + else: + ensure_not_tainted(s) + + +def test_tricky(): + s = TAINTED_STRING + + x = is_safe(s) + if x: + ensure_not_tainted(s) # FP + + s_ = s + if is_safe(s): + ensure_not_tainted(s_) # FP + +def test_nesting_not(): + s = TAINTED_STRING + + if not(not(is_safe(s))): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not(not(not(is_safe(s)))): + ensure_tainted(s) + else: + ensure_not_tainted(s) + +# Adding `and True` makes the sanitizer trigger when it would otherwise not. See output in +# SanitizedEdges.expected and compare with `test_nesting_not` and `test_basic` +def test_nesting_not_with_and_true(): + s = TAINTED_STRING + + if not(is_safe(s) and True): + ensure_tainted(s) + else: + ensure_not_tainted(s) + + if not(not(is_safe(s) and True)): + ensure_not_tainted(s) + else: + ensure_tainted(s) + + if not(not(not(is_safe(s) and True))): + ensure_tainted(s) + else: + ensure_not_tainted(s) diff --git a/python/ql/test/library-tests/exceptions/Handles.ql b/python/ql/test/library-tests/exceptions/Handles.ql index 989126b7127..620944de5b9 100644 --- a/python/ql/test/library-tests/exceptions/Handles.ql +++ b/python/ql/test/library-tests/exceptions/Handles.ql @@ -2,4 +2,4 @@ import python from ExceptFlowNode ex, Value val where ex.handledException(val, _, _) -select ex.getLocation().getStartLine(), ex.toString(), val.toString() \ No newline at end of file +select ex.getLocation().getStartLine(), ex.toString(), val.toString() diff --git a/python/ql/test/library-tests/exceptions/Legal.ql b/python/ql/test/library-tests/exceptions/Legal.ql index 37488eb082b..eb27a82d614 100644 --- a/python/ql/test/library-tests/exceptions/Legal.ql +++ b/python/ql/test/library-tests/exceptions/Legal.ql @@ -2,10 +2,9 @@ import python from ClassObject cls, string legal where -not cls.isC() and cls.isLegalExceptionType() and legal = "yes" and not cls.failedInference() -or -not cls.isC() and not cls.isLegalExceptionType() and legal = "no" and not cls.failedInference() -or -not cls.isC() and cls.failedInference(legal) - + not cls.isC() and cls.isLegalExceptionType() and legal = "yes" and not cls.failedInference() + or + not cls.isC() and not cls.isLegalExceptionType() and legal = "no" and not cls.failedInference() + or + not cls.isC() and cls.failedInference(legal) select cls.toString(), legal diff --git a/python/ql/test/library-tests/exprs/ast/AstParent.ql b/python/ql/test/library-tests/exprs/ast/AstParent.ql index 3e26f672360..f472a6f6e5b 100644 --- a/python/ql/test/library-tests/exprs/ast/AstParent.ql +++ b/python/ql/test/library-tests/exprs/ast/AstParent.ql @@ -1,6 +1,4 @@ import python -select -count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) -+ -count(AstNode c | strictcount(c.getParentNode()) > 1) \ No newline at end of file +select count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) + + count(AstNode c | strictcount(c.getParentNode()) > 1) diff --git a/python/ql/test/library-tests/exprs/ast/Child.ql b/python/ql/test/library-tests/exprs/ast/Child.ql index 0638f6c4e22..5b363a6ddb2 100644 --- a/python/ql/test/library-tests/exprs/ast/Child.ql +++ b/python/ql/test/library-tests/exprs/ast/Child.ql @@ -3,4 +3,3 @@ import python from AstNode p, AstNode c where p.getAChildNode() = c select p.getLocation().getStartLine(), p.toString(), c.getLocation().getStartLine(), c - diff --git a/python/ql/test/library-tests/exprs/compare/Test.ql b/python/ql/test/library-tests/exprs/compare/Test.ql index 7aa2102f8b8..80feac5185a 100644 --- a/python/ql/test/library-tests/exprs/compare/Test.ql +++ b/python/ql/test/library-tests/exprs/compare/Test.ql @@ -1,8 +1,6 @@ - import python import semmle.python.TestUtils - from Compare comp, Expr left, Expr right, Cmpop op where comp.compares(left, op, right) select compact_location(comp), comp.toString(), left.toString(), op.toString(), right.toString() diff --git a/python/ql/test/library-tests/exprs/strings/Strings.ql b/python/ql/test/library-tests/exprs/strings/Strings.ql index e3a757c4725..7d6a697a8ed 100644 --- a/python/ql/test/library-tests/exprs/strings/Strings.ql +++ b/python/ql/test/library-tests/exprs/strings/Strings.ql @@ -1,4 +1,3 @@ - import python from StrConst s diff --git a/python/ql/test/library-tests/filters/generated/Filter.ql b/python/ql/test/library-tests/filters/generated/Filter.ql index 39c0e2b2344..389440ffd3a 100644 --- a/python/ql/test/library-tests/filters/generated/Filter.ql +++ b/python/ql/test/library-tests/filters/generated/Filter.ql @@ -1,4 +1,3 @@ - import python import semmle.python.filters.GeneratedCode diff --git a/python/ql/test/library-tests/filters/tests/Filter.ql b/python/ql/test/library-tests/filters/tests/Filter.ql index e20231ea5fa..71d6d2c668d 100644 --- a/python/ql/test/library-tests/filters/tests/Filter.ql +++ b/python/ql/test/library-tests/filters/tests/Filter.ql @@ -1,4 +1,3 @@ - import python import semmle.python.filters.Tests diff --git a/python/ql/test/library-tests/formatting/FormatArguments.ql b/python/ql/test/library-tests/formatting/FormatArguments.ql index 19e47b7fc44..f2cc38f7e8c 100644 --- a/python/ql/test/library-tests/formatting/FormatArguments.ql +++ b/python/ql/test/library-tests/formatting/FormatArguments.ql @@ -1,10 +1,9 @@ - import python import Expressions.Formatting.AdvancedFormatting from AdvancedFormatString a, string name, int start, int end -where -name = "'" + a.getFieldName(start, end) + "'" -or -name = a.getFieldNumber(start, end).toString() +where + name = "'" + a.getFieldName(start, end) + "'" + or + name = a.getFieldNumber(start, end).toString() select a.getLocation().getStartLine(), a.getText(), start, end, name diff --git a/python/ql/test/library-tests/formatting/FormatFields.ql b/python/ql/test/library-tests/formatting/FormatFields.ql index b8a3b913355..f629a779082 100644 --- a/python/ql/test/library-tests/formatting/FormatFields.ql +++ b/python/ql/test/library-tests/formatting/FormatFields.ql @@ -1,4 +1,3 @@ - import python import Expressions.Formatting.AdvancedFormatting diff --git a/python/ql/test/library-tests/imports/Alias.ql b/python/ql/test/library-tests/imports/Alias.ql index 5a7c034d02a..a08d1c6543b 100644 --- a/python/ql/test/library-tests/imports/Alias.ql +++ b/python/ql/test/library-tests/imports/Alias.ql @@ -2,4 +2,4 @@ import python from Alias a, ImportMember i where i = a.getValue() -select a.toString(), i.getName(), a.getAsname().toString() \ No newline at end of file +select a.toString(), i.getName(), a.getAsname().toString() diff --git a/python/ql/test/library-tests/jump_to_defn/Remote.ql b/python/ql/test/library-tests/jump_to_defn/Remote.ql index 18b0ebacdc0..7602e5839d3 100644 --- a/python/ql/test/library-tests/jump_to_defn/Remote.ql +++ b/python/ql/test/library-tests/jump_to_defn/Remote.ql @@ -1,10 +1,10 @@ - import python import analysis.DefinitionTracking import analysis.CrossProjectDefinitions from Definition defn, Symbol s -where s.find() = defn.getAstNode() and -// Exclude dunder names as these vary from version to version. -not s.toString().regexpMatch(".+__") +where + s.find() = defn.getAstNode() and + // Exclude dunder names as these vary from version to version. + not s.toString().regexpMatch(".+__") select s.toString() diff --git a/python/ql/test/library-tests/jump_to_defn/Sanity.ql b/python/ql/test/library-tests/jump_to_defn/Sanity.ql index 0e4455ab09b..ba274e0aa21 100644 --- a/python/ql/test/library-tests/jump_to_defn/Sanity.ql +++ b/python/ql/test/library-tests/jump_to_defn/Sanity.ql @@ -1,4 +1,3 @@ - import python import analysis.DefinitionTracking import analysis.CrossProjectDefinitions @@ -6,11 +5,11 @@ import analysis.CrossProjectDefinitions predicate local_problem(Definition defn, string issue, string repr) { not exists(defn.toString()) and issue = "no toString()" and repr = "a local definition" or - not exists(defn.getAstNode()) and issue = "no getAstNode()" and repr = defn.toString() + not exists(defn.getAstNode()) and issue = "no getAstNode()" and repr = defn.toString() or - not exists(defn.getLocation()) and issue = "no getLocation()" and repr = defn.toString() + not exists(defn.getLocation()) and issue = "no getLocation()" and repr = defn.toString() or - count(defn.getLocation())> 1 and issue = "more than one getLocation()" and repr = defn.toString() + count(defn.getLocation()) > 1 and issue = "more than one getLocation()" and repr = defn.toString() } predicate remote_problem(Symbol s, string issue, string repr) { diff --git a/python/ql/test/library-tests/jump_to_defn/Symbol.ql b/python/ql/test/library-tests/jump_to_defn/Symbol.ql index 7f111863b06..446f6b47b51 100644 --- a/python/ql/test/library-tests/jump_to_defn/Symbol.ql +++ b/python/ql/test/library-tests/jump_to_defn/Symbol.ql @@ -1,8 +1,5 @@ - import python import analysis.CrossProjectDefinitions from Symbol symbol - select symbol.toString(), symbol.find().getLocation().toString() - diff --git a/python/ql/test/library-tests/jump_to_defn/test.ql b/python/ql/test/library-tests/jump_to_defn/test.ql index ed8bf8ab84c..0f952578997 100644 --- a/python/ql/test/library-tests/jump_to_defn/test.ql +++ b/python/ql/test/library-tests/jump_to_defn/test.ql @@ -6,6 +6,7 @@ import python import analysis.DefinitionTracking from Expr use, Definition defn -where defn = getADefinition(use) -and use.getEnclosingModule().getName() = "test" +where + defn = getADefinition(use) and + use.getEnclosingModule().getName() = "test" select use.getLocation().toString(), use.toString(), defn.toString() diff --git a/python/ql/test/library-tests/locations/elif/test.ql b/python/ql/test/library-tests/locations/elif/test.ql index ca7177e847c..b2e7f4b164d 100644 --- a/python/ql/test/library-tests/locations/elif/test.ql +++ b/python/ql/test/library-tests/locations/elif/test.ql @@ -2,4 +2,4 @@ import python from AstNode ast, Location l where ast.getLocation() = l -select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() \ No newline at end of file +select ast.getAQlClass(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql b/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql index 2687a785f1b..aac64976f75 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/part_locations.ql @@ -1,12 +1,9 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StringPart s - - -select s.getLocation().getStartLine(), s.getText(), s.getLocation().getStartColumn(), s.getLocation().getEndColumn() \ No newline at end of file +select s.getLocation().getStartLine(), s.getText(), s.getLocation().getStartColumn(), + s.getLocation().getEndColumn() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql b/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql index 1b1a0d492b3..49fe354b6ee 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/parts.ql @@ -1,14 +1,9 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StrConst s, StringPart part, int n -where - part = s.getImplicitlyConcatenatedPart(n) - - -select s.getLocation().getStartLine(), s.getText(), n, part.getText() \ No newline at end of file +where part = s.getImplicitlyConcatenatedPart(n) +select s.getLocation().getStartLine(), s.getText(), n, part.getText() diff --git a/python/ql/test/library-tests/locations/implicit_concatenation/test.ql b/python/ql/test/library-tests/locations/implicit_concatenation/test.ql index 5b2f6ae0a55..09ba3dcd1c4 100644 --- a/python/ql/test/library-tests/locations/implicit_concatenation/test.ql +++ b/python/ql/test/library-tests/locations/implicit_concatenation/test.ql @@ -1,16 +1,13 @@ import python class ImplicitConcat extends StrConst { - ImplicitConcat() { - exists(this.getAnImplicitlyConcatenatedPart()) - } + ImplicitConcat() { exists(this.getAnImplicitlyConcatenatedPart()) } } - + from StrConst s, boolean isConcat -where - s instanceof ImplicitConcat and isConcat = true - or - not s instanceof ImplicitConcat and isConcat = false - - -select s.getLocation().getStartLine(), s.getText(), isConcat, s.getText().length(), s.getLocation().getStartColumn(), s.getLocation().getEndColumn() \ No newline at end of file +where + s instanceof ImplicitConcat and isConcat = true + or + not s instanceof ImplicitConcat and isConcat = false +select s.getLocation().getStartLine(), s.getText(), isConcat, s.getText().length(), + s.getLocation().getStartColumn(), s.getLocation().getEndColumn() diff --git a/python/ql/test/library-tests/locations/negative_numbers/negative.ql b/python/ql/test/library-tests/locations/negative_numbers/negative.ql index c423cb0532c..0fe2cdcc2bc 100644 --- a/python/ql/test/library-tests/locations/negative_numbers/negative.ql +++ b/python/ql/test/library-tests/locations/negative_numbers/negative.ql @@ -1,13 +1,7 @@ import python -from Expr e, int bl, int bc, int el,int ec, string p - -where - e.getLocation().hasLocationInfo(_, bl, bc, el, ec) - and - if e.isParenthesized() then - p = "()" - else - p = "" - -select e.toString(), bl, bc, el, ec, p \ No newline at end of file +from Expr e, int bl, int bc, int el, int ec, string p +where + e.getLocation().hasLocationInfo(_, bl, bc, el, ec) and + if e.isParenthesized() then p = "()" else p = "" +select e.toString(), bl, bc, el, ec, p diff --git a/python/ql/test/library-tests/locations/nested_classes/Test.ql b/python/ql/test/library-tests/locations/nested_classes/Test.ql index 693d6f7116f..143df5fee6f 100644 --- a/python/ql/test/library-tests/locations/nested_classes/Test.ql +++ b/python/ql/test/library-tests/locations/nested_classes/Test.ql @@ -1,7 +1,5 @@ - import python from Class cls, Location l where l = cls.getLocation() - select cls.getName(), l.getStartLine(), l.getStartColumn(), l.getEndLine(), l.getEndColumn() diff --git a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql index 536689d0f90..a6477c7d6af 100644 --- a/python/ql/test/library-tests/modules/duplicate_name/Modules.ql +++ b/python/ql/test/library-tests/modules/duplicate_name/Modules.ql @@ -1,7 +1,5 @@ - import python from string name, int mcnt where mcnt = strictcount(Module m | m.getName() = name) and mcnt > 1 select name, mcnt, strictcount(ModuleValue val | val.getName() = name) - diff --git a/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql b/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql index a3a54953513..bc7bc0526ec 100644 --- a/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql +++ b/python/ql/test/library-tests/modules/overlapping-paths/ModuleNames.ql @@ -1,4 +1,3 @@ - import python from Module m diff --git a/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql b/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql index a3a54953513..bc7bc0526ec 100644 --- a/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql +++ b/python/ql/test/library-tests/modules/spurious_init/ModuleNames.ql @@ -1,4 +1,3 @@ - import python from Module m diff --git a/python/ql/test/library-tests/objects/Literals.ql b/python/ql/test/library-tests/objects/Literals.ql index f83f4e722da..ad6e1181cfd 100644 --- a/python/ql/test/library-tests/objects/Literals.ql +++ b/python/ql/test/library-tests/objects/Literals.ql @@ -1,8 +1,6 @@ - /* Test that there are no literals that do not have a corresponding object. */ import python - string repr(Expr e) { result = e.(Num).getN() or result = e.(Bytes).getS() or @@ -10,7 +8,5 @@ string repr(Expr e) { } from ImmutableLiteral l -where -not exists(l.getLiteralObject()) - -select l.getLocation().getStartLine(), repr(l) \ No newline at end of file +where not exists(l.getLiteralObject()) +select l.getLocation().getStartLine(), repr(l) diff --git a/python/ql/test/library-tests/objects/Name.ql b/python/ql/test/library-tests/objects/Name.ql index 674890c01ba..c20358b9062 100644 --- a/python/ql/test/library-tests/objects/Name.ql +++ b/python/ql/test/library-tests/objects/Name.ql @@ -1,21 +1,21 @@ - import python from Object o, string name -where o.hasLongName(name) -and ( - name = "sys.modules" - or - name = "test.n" - or - name = "test.l" - or - name = "test.d" - or - name = "test.C.meth" - or - name = "test.C.cmeth" - or - name = "test.C.smeth" -) +where + o.hasLongName(name) and + ( + name = "sys.modules" + or + name = "test.n" + or + name = "test.l" + or + name = "test.d" + or + name = "test.C.meth" + or + name = "test.C.cmeth" + or + name = "test.C.smeth" + ) select name, o.toString() diff --git a/python/ql/test/library-tests/objects/Strings.ql b/python/ql/test/library-tests/objects/Strings.ql index 9fcceb58fe4..eca8dec51fd 100644 --- a/python/ql/test/library-tests/objects/Strings.ql +++ b/python/ql/test/library-tests/objects/Strings.ql @@ -1,8 +1,5 @@ - import python - from StringObject s, ControlFlowNode f where f.refersTo(s) select f.getLocation().toString(), s.getText() - diff --git a/python/ql/test/library-tests/parameters/Annotations.ql b/python/ql/test/library-tests/parameters/Annotations.ql index cceecd699f3..17b02844a44 100644 --- a/python/ql/test/library-tests/parameters/Annotations.ql +++ b/python/ql/test/library-tests/parameters/Annotations.ql @@ -1,6 +1,4 @@ - import python - from Parameter p select p.getName(), p.getAnnotation() diff --git a/python/ql/test/library-tests/parameters/Defaults.ql b/python/ql/test/library-tests/parameters/Defaults.ql index ab16913804d..ebc8215074b 100644 --- a/python/ql/test/library-tests/parameters/Defaults.ql +++ b/python/ql/test/library-tests/parameters/Defaults.ql @@ -1,6 +1,4 @@ - import python - from Parameter p select p.getName(), p.getDefault() diff --git a/python/ql/test/library-tests/parameters/Special.ql b/python/ql/test/library-tests/parameters/Special.ql index ff06b8f072d..4987599bc72 100644 --- a/python/ql/test/library-tests/parameters/Special.ql +++ b/python/ql/test/library-tests/parameters/Special.ql @@ -1,13 +1,10 @@ - - import python from Parameter p, string type where -p.isKwargs() and type = "kwargs" -or -p.isVarargs() and type = "varargs" -or -not p.isKwargs() and not p.isVarargs() and type = "normal" - + p.isKwargs() and type = "kwargs" + or + p.isVarargs() and type = "varargs" + or + not p.isKwargs() and not p.isVarargs() and type = "normal" select p.getName(), type diff --git a/python/ql/test/library-tests/regex/Alternation.ql b/python/ql/test/library-tests/regex/Alternation.ql index 210d26aad98..79622fae32e 100644 --- a/python/ql/test/library-tests/regex/Alternation.ql +++ b/python/ql/test/library-tests/regex/Alternation.ql @@ -1,8 +1,7 @@ - import python import semmle.python.regex from Regex r, int start, int end, int part_start, int part_end where r.alternationOption(start, end, part_start, part_end) -select r.getText(), start, end, r.getText().substring(start, end), - part_start, part_end, r.getText().substring(part_start, part_end) +select r.getText(), start, end, r.getText().substring(start, end), part_start, part_end, + r.getText().substring(part_start, part_end) diff --git a/python/ql/test/library-tests/regex/Characters.ql b/python/ql/test/library-tests/regex/Characters.ql index 38976fcf7c7..1444c37cd57 100644 --- a/python/ql/test/library-tests/regex/Characters.ql +++ b/python/ql/test/library-tests/regex/Characters.ql @@ -3,12 +3,9 @@ * @description Test for escaped characters */ - import python import semmle.python.regex from Regex r, int start, int end where r.character(start, end) and r.getLocation().getFile().getBaseName() = "test.py" select r.getText(), start, end - - diff --git a/python/ql/test/library-tests/regex/FirstLast.ql b/python/ql/test/library-tests/regex/FirstLast.ql index 0ca7e10cd3a..7a57eb51382 100644 --- a/python/ql/test/library-tests/regex/FirstLast.ql +++ b/python/ql/test/library-tests/regex/FirstLast.ql @@ -1,10 +1,8 @@ - - import python import semmle.python.regex predicate part(Regex r, int start, int end, string kind) { - r.lastItem(start, end) and kind = "last" + r.lastItem(start, end) and kind = "last" or r.firstItem(start, end) and kind = "first" } diff --git a/python/ql/test/library-tests/regex/GroupContents.ql b/python/ql/test/library-tests/regex/GroupContents.ql index 1b49f5d9efd..28ad5749c0a 100644 --- a/python/ql/test/library-tests/regex/GroupContents.ql +++ b/python/ql/test/library-tests/regex/GroupContents.ql @@ -1,8 +1,7 @@ - import python import semmle.python.regex from Regex r, int start, int end, int part_start, int part_end where r.groupContents(start, end, part_start, part_end) -select r.getText(), start, end, r.getText().substring(start, end), - part_start, part_end, r.getText().substring(part_start, part_end) \ No newline at end of file +select r.getText(), start, end, r.getText().substring(start, end), part_start, part_end, + r.getText().substring(part_start, part_end) diff --git a/python/ql/test/library-tests/regex/Mode.ql b/python/ql/test/library-tests/regex/Mode.ql index 7fd593075a9..02e84f86c5d 100644 --- a/python/ql/test/library-tests/regex/Mode.ql +++ b/python/ql/test/library-tests/regex/Mode.ql @@ -1,7 +1,4 @@ - import python - - import semmle.python.regex from Regex r diff --git a/python/ql/test/library-tests/regex/Qualified.ql b/python/ql/test/library-tests/regex/Qualified.ql index e40d2bf6ae7..8adf7e0426c 100644 --- a/python/ql/test/library-tests/regex/Qualified.ql +++ b/python/ql/test/library-tests/regex/Qualified.ql @@ -1,5 +1,3 @@ - - import python import semmle.python.regex diff --git a/python/ql/test/library-tests/regex/Regex.ql b/python/ql/test/library-tests/regex/Regex.ql index 220efdb4cc3..708ad82804d 100644 --- a/python/ql/test/library-tests/regex/Regex.ql +++ b/python/ql/test/library-tests/regex/Regex.ql @@ -1,10 +1,8 @@ - - import python import semmle.python.regex predicate part(Regex r, int start, int end, string kind) { - r.alternation(start, end) and kind = "choice" + r.alternation(start, end) and kind = "choice" or r.normalCharacter(start, end) and kind = "char" or diff --git a/python/ql/test/library-tests/scopes/Previous.ql b/python/ql/test/library-tests/scopes/Previous.ql index 1e7d25d7da8..00bd2b90f2a 100644 --- a/python/ql/test/library-tests/scopes/Previous.ql +++ b/python/ql/test/library-tests/scopes/Previous.ql @@ -2,4 +2,4 @@ import python from Scope s1, Scope s2 where s1.precedes(s2) -select s1.toString(), s2.toString() \ No newline at end of file +select s1.toString(), s2.toString() diff --git a/python/ql/test/library-tests/security/sensitive/Sources.ql b/python/ql/test/library-tests/security/sensitive/Sources.ql index f974c18780a..b5328a9f105 100644 --- a/python/ql/test/library-tests/security/sensitive/Sources.ql +++ b/python/ql/test/library-tests/security/sensitive/Sources.ql @@ -1,6 +1,4 @@ - import python - import semmle.python.security.SensitiveData from SensitiveData::Source src diff --git a/python/ql/test/library-tests/state_tracking/Lib.qll b/python/ql/test/library-tests/state_tracking/Lib.qll index f2c0db3c296..e784b7e198b 100644 --- a/python/ql/test/library-tests/state_tracking/Lib.qll +++ b/python/ql/test/library-tests/state_tracking/Lib.qll @@ -1,31 +1,18 @@ import python import semmle.python.dataflow.StateTracking -predicate callTo(CallNode call, string name) { - call.getFunction().(NameNode).getId() = name -} +predicate callTo(CallNode call, string name) { call.getFunction().(NameNode).getId() = name } class Initialized extends TrackableState { - Initialized() { this = "initialized" } - override predicate startsAt(ControlFlowNode f) { - callTo(f, "initialize") - } - + override predicate startsAt(ControlFlowNode f) { callTo(f, "initialize") } } - class Frobnicated extends TrackableState { - Frobnicated() { this = "frobnicated" } - override predicate startsAt(ControlFlowNode f) { - callTo(f, "frobnicate") - } - - override predicate endsAt(ControlFlowNode f) { - callTo(f, "defrobnicate") - } + override predicate startsAt(ControlFlowNode f) { callTo(f, "frobnicate") } + override predicate endsAt(ControlFlowNode f) { callTo(f, "defrobnicate") } } diff --git a/python/ql/test/library-tests/state_tracking/Test.ql b/python/ql/test/library-tests/state_tracking/Test.ql index e88365aad94..cfdfa7c77aa 100644 --- a/python/ql/test/library-tests/state_tracking/Test.ql +++ b/python/ql/test/library-tests/state_tracking/Test.ql @@ -1,14 +1,12 @@ - import python import Lib from ControlFlowNode f, TrackableState state, Context ctx, boolean sense where -f.getLocation().getStartLine() >= 20 and -( - state.appliesTo(f, ctx) and sense = true - or - state.mayNotApplyTo(f, ctx) and sense = false -) - + f.getLocation().getStartLine() >= 20 and + ( + state.appliesTo(f, ctx) and sense = true + or + state.mayNotApplyTo(f, ctx) and sense = false + ) select f.getLocation().toString(), f, ctx, state, sense diff --git a/python/ql/test/library-tests/state_tracking/Violations.ql b/python/ql/test/library-tests/state_tracking/Violations.ql index 8da2a0500ef..db70e7d3368 100644 --- a/python/ql/test/library-tests/state_tracking/Violations.ql +++ b/python/ql/test/library-tests/state_tracking/Violations.ql @@ -1,15 +1,12 @@ - import python import Lib from ControlFlowNode f, TrackableState state where -( - callTo(f, "exacerbate") and state = "frobnicated" - or - callTo(f, "frobnicate") and state = "initialized" -) -and -state.mayNotApplyTo(f) - + ( + callTo(f, "exacerbate") and state = "frobnicated" + or + callTo(f, "frobnicate") and state = "initialized" + ) and + state.mayNotApplyTo(f) select f.getLocation().toString(), f.toString(), state.toString() diff --git a/python/ql/test/library-tests/stmts/general/AstParent.ql b/python/ql/test/library-tests/stmts/general/AstParent.ql index b7ea6f44ac3..85e0f4947fa 100644 --- a/python/ql/test/library-tests/stmts/general/AstParent.ql +++ b/python/ql/test/library-tests/stmts/general/AstParent.ql @@ -1,8 +1,5 @@ import python /* The result of this query should always be 0, *regardless* of the database. */ - -select -count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) -+ -count(AstNode c | strictcount(c.getParentNode()) > 1) +select count(AstNode c | not exists(c.getParentNode()) and not c instanceof Module) + + count(AstNode c | strictcount(c.getParentNode()) > 1) diff --git a/python/ql/test/library-tests/stmts/general/SubExpressions.ql b/python/ql/test/library-tests/stmts/general/SubExpressions.ql index deaff1e9610..e3b5eed1ced 100644 --- a/python/ql/test/library-tests/stmts/general/SubExpressions.ql +++ b/python/ql/test/library-tests/stmts/general/SubExpressions.ql @@ -1,5 +1,5 @@ - import python from Stmt s -select s.toString(), s.getASubExpression().toString(), s.getASubExpression().getASubExpression*().toString(), s.getLocation().getStartLine() \ No newline at end of file +select s.toString(), s.getASubExpression().toString(), + s.getASubExpression().getASubExpression*().toString(), s.getLocation().getStartLine() diff --git a/python/ql/test/library-tests/stmts/raise_stmt/AST.ql b/python/ql/test/library-tests/stmts/raise_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/raise_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/raise_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/stmts/try_stmt/AST.ql b/python/ql/test/library-tests/stmts/try_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/try_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/try_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/stmts/with_stmt/AST.ql b/python/ql/test/library-tests/stmts/with_stmt/AST.ql index d9daaa8514b..62719f1179f 100644 --- a/python/ql/test/library-tests/stmts/with_stmt/AST.ql +++ b/python/ql/test/library-tests/stmts/with_stmt/AST.ql @@ -1,7 +1,6 @@ - - import python from AstNode parent, AstNode child where child.getParentNode() = parent -select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), child.toString() \ No newline at end of file +select parent.getLocation().getStartLine(), parent.toString(), child.getLocation().getStartLine(), + child.toString() diff --git a/python/ql/test/library-tests/taint/collections/Taint.qll b/python/ql/test/library-tests/taint/collections/Taint.qll index b61870722b8..b97f65225f2 100644 --- a/python/ql/test/library-tests/taint/collections/Taint.qll +++ b/python/ql/test/library-tests/taint/collections/Taint.qll @@ -2,45 +2,26 @@ import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted - class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringKind - } - - override string toString() { - result = "taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + override string toString() { result = "taint source" } } class ListSource extends TaintSource { - ListSource() { this.(NameNode).getId() = "TAINTED_LIST" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringSequenceKind - } - - override string toString() { - result = "list taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind } + override string toString() { result = "list taint source" } } class DictSource extends TaintSource { - DictSource() { this.(NameNode).getId() = "TAINTED_DICT" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringDictKind - } - - override string toString() { - result = "dict taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind } + override string toString() { result = "dict taint source" } } diff --git a/python/ql/test/library-tests/taint/collections/TestTaint.ql b/python/ql/test/library-tests/taint/collections/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/collections/TestTaint.ql +++ b/python/ql/test/library-tests/taint/collections/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/config/RockPaperScissors.ql b/python/ql/test/library-tests/taint/config/RockPaperScissors.ql index 0910f9846c4..311039a6553 100644 --- a/python/ql/test/library-tests/taint/config/RockPaperScissors.ql +++ b/python/ql/test/library-tests/taint/config/RockPaperScissors.ql @@ -1,4 +1,3 @@ - /** * @kind path-problem */ @@ -10,4 +9,5 @@ import semmle.python.security.Paths from RockPaperScissorConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ loses to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString() \ No newline at end of file +select sink.getSink(), src, sink, "$@ loses to $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), sink.getTaintKind().toString() diff --git a/python/ql/test/library-tests/taint/config/Simple.ql b/python/ql/test/library-tests/taint/config/Simple.ql index a3acf7272f6..76e8c261048 100644 --- a/python/ql/test/library-tests/taint/config/Simple.ql +++ b/python/ql/test/library-tests/taint/config/Simple.ql @@ -1,4 +1,3 @@ - /** * @kind path-problem */ @@ -10,4 +9,5 @@ import semmle.python.security.Paths from SimpleConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ flows to $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), sink.getTaintKind().toString() +select sink.getSink(), src, sink, "$@ flows to $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), sink.getTaintKind().toString() diff --git a/python/ql/test/library-tests/taint/config/TaintLib.qll b/python/ql/test/library-tests/taint/config/TaintLib.qll index dd9a0186a35..670a9515c33 100644 --- a/python/ql/test/library-tests/taint/config/TaintLib.qll +++ b/python/ql/test/library-tests/taint/config/TaintLib.qll @@ -1,24 +1,16 @@ import python import semmle.python.security.TaintTracking - class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } abstract class TestConfig extends TaintTracking::Configuration { - bindingset[this] TestConfig() { any() } - } class SimpleConfig extends TestConfig { - SimpleConfig() { this = "Simple config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -38,26 +30,19 @@ class SimpleConfig extends TestConfig { node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and kind instanceof SimpleTest } - } class BasicCustomTaint extends TaintKind { - - BasicCustomTaint() { - this = "basic.custom" - } + BasicCustomTaint() { this = "basic.custom" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(CallNode).getAnArg() = fromnode and tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and result = this } - } - class BasicCustomConfig extends TestConfig { - BasicCustomConfig() { this = "Basic custom config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -72,57 +57,46 @@ class BasicCustomConfig extends TestConfig { ) and kind instanceof SimpleTest } - } - class Rock extends TaintKind { - Rock() { this = "rock" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Scissors } - } class Paper extends TaintKind { - Paper() { this = "paper" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Rock } - } class Scissors extends TaintKind { - Scissors() { this = "scissors" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Paper } - } class RockPaperScissorConfig extends TestConfig { - RockPaperScissorConfig() { this = "Rock-paper-scissors config" } - override predicate isSource(DataFlow::Node node, TaintKind kind) { exists(string name | node.asCfgNode().(NameNode).getId() = name and kind = name.toLowerCase() - | + | name = "ROCK" or name = "PAPER" or name = "SCISSORS" ) } override predicate isSink(DataFlow::Node node, TaintKind kind) { - exists(string name | - function_param(name, node) | + exists(string name | function_param(name, node) | name = "paper" and kind = "rock" or name = "rock" and kind = "scissors" @@ -130,7 +104,6 @@ class RockPaperScissorConfig extends TestConfig { name = "scissors" and kind = "paper" ) } - } private predicate function_param(string funcname, DataFlow::Node arg) { @@ -140,20 +113,15 @@ private predicate function_param(string funcname, DataFlow::Node arg) { ) } - class TaintCarrier extends TaintKind { - TaintCarrier() { this = "explicit.carrier" } override TaintKind getTaintOfMethodResult(string name) { name = "get_taint" and result instanceof SimpleTest } - - } class TaintCarrierConfig extends TestConfig { - TaintCarrierConfig() { this = "Taint carrier config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -173,49 +141,31 @@ class TaintCarrierConfig extends TestConfig { node.asCfgNode().(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and kind instanceof SimpleTest } - } - /* Some more realistic examples */ - abstract class UserInput extends TaintKind { - bindingset[this] UserInput() { any() } - } class UserInputSource extends TaintSource { + UserInputSource() { this.(CallNode).getFunction().(NameNode).getId() = "user_input" } - UserInputSource() { - this.(CallNode).getFunction().(NameNode).getId() = "user_input" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof UserInput - } - - override string toString() { - result = "user.input.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof UserInput } + override string toString() { result = "user.input.source" } } class SqlInjectionTaint extends UserInput { - SqlInjectionTaint() { this = "SQL injection" } - } class CommandInjectionTaint extends UserInput { - CommandInjectionTaint() { this = "Command injection" } - } class SqlSanitizer extends Sanitizer { - SqlSanitizer() { this = "SQL sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -229,11 +179,9 @@ class SqlSanitizer extends Sanitizer { ) and taint instanceof SqlInjectionTaint } - } class CommandSanitizer extends Sanitizer { - CommandSanitizer() { this = "Command sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -245,11 +193,9 @@ class CommandSanitizer extends Sanitizer { ) and taint instanceof CommandInjectionTaint } - } class SqlQuery extends TaintSink { - SqlQuery() { exists(CallNode call | call.getFunction().(NameNode).getId() = "sql_query" and @@ -259,15 +205,10 @@ class SqlQuery extends TaintSink { override string toString() { result = "SQL query" } - override predicate sinks(TaintKind taint) { - taint instanceof SqlInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof SqlInjectionTaint } } - class OsCommand extends TaintSink { - OsCommand() { exists(CallNode call | call.getFunction().(NameNode).getId() = "os_command" and @@ -277,60 +218,31 @@ class OsCommand extends TaintSink { override string toString() { result = "OS command" } - override predicate sinks(TaintKind taint) { - taint instanceof CommandInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof CommandInjectionTaint } } - class Falsey extends TaintKind { - Falsey() { this = "falsey" } - override boolean booleanValue() { - result = false - } - + override boolean booleanValue() { result = false } } -class FalseySource extends TaintSource { +class FalseySource extends TaintSource { + FalseySource() { this.(NameNode).getId() = "FALSEY" } - FalseySource() { - this.(NameNode).getId() = "FALSEY" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof Falsey - } - - override string toString() { - result = "falsey.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof Falsey } + override string toString() { result = "falsey.source" } } class TaintIterable extends TaintKind { + TaintIterable() { this = "iterable.simple" } - TaintIterable() { - this = "iterable.simple" - } - - override TaintKind getTaintForIteration() { - result instanceof SimpleTest - } - + override TaintKind getTaintForIteration() { result instanceof SimpleTest } } class TaintIterableSource extends TaintSource { + TaintIterableSource() { this.(NameNode).getId() = "ITERABLE_SOURCE" } - TaintIterableSource() { - this.(NameNode).getId() = "ITERABLE_SOURCE" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintIterable - } - + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintIterable } } - diff --git a/python/ql/test/library-tests/taint/config/TaintedArgument.ql b/python/ql/test/library-tests/taint/config/TaintedArgument.ql index 9cbde79561b..ca351d878a5 100644 --- a/python/ql/test/library-tests/taint/config/TaintedArgument.ql +++ b/python/ql/test/library-tests/taint/config/TaintedArgument.ql @@ -1,14 +1,12 @@ - import python - - - import semmle.python.security.TaintTracking import TaintLib import semmle.python.dataflow.Implementation -from TaintTrackingImplementation config, TaintTrackingNode src, CallNode call, - TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind -where config instanceof TestConfig and -config.callWithTaintedArgument(src, call, caller, pyfunc, arg, path, kind) +from + TaintTrackingImplementation config, TaintTrackingNode src, CallNode call, + TaintTrackingContext caller, CallableValue pyfunc, int arg, AttributePath path, TaintKind kind +where + config instanceof TestConfig and + config.callWithTaintedArgument(src, call, caller, pyfunc, arg, path, kind) select config, src, call, caller, pyfunc, arg, path, kind diff --git a/python/ql/test/library-tests/taint/config/TestNode.ql b/python/ql/test/library-tests/taint/config/TestNode.ql index 165bf382301..02a4dd278c3 100644 --- a/python/ql/test/library-tests/taint/config/TestNode.ql +++ b/python/ql/test/library-tests/taint/config/TestNode.ql @@ -3,8 +3,7 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import TaintLib - from TaintTrackingNode n where n.getConfiguration() instanceof TestConfig -select n.getLocation().toString(), n.getTaintKind(), n.getNode().toString(), n.getPath().toString(), n.getContext().toString() - +select n.getLocation().toString(), n.getTaintKind(), n.getNode().toString(), n.getPath().toString(), + n.getContext().toString() diff --git a/python/ql/test/library-tests/taint/config/TestSink.ql b/python/ql/test/library-tests/taint/config/TestSink.ql index 2fc42bce378..4df3f48b939 100644 --- a/python/ql/test/library-tests/taint/config/TestSink.ql +++ b/python/ql/test/library-tests/taint/config/TestSink.ql @@ -3,6 +3,5 @@ import semmle.python.security.TaintTracking import TaintLib from TestConfig config, DataFlow::Node sink, TaintKind kind - where config.isSink(sink, kind) select sink.getLocation().toString(), config, sink.toString(), kind diff --git a/python/ql/test/library-tests/taint/config/TestSource.ql b/python/ql/test/library-tests/taint/config/TestSource.ql index 338ec65fd45..191583becb7 100644 --- a/python/ql/test/library-tests/taint/config/TestSource.ql +++ b/python/ql/test/library-tests/taint/config/TestSource.ql @@ -3,6 +3,6 @@ import semmle.python.security.TaintTracking import TaintLib from TestConfig config, DataFlow::Node source, TaintKind kind - where config.isSource(source, kind) -select config, source.getLocation().toString(), source.getLocation().getStartLine(), source.toString(), kind +select config, source.getLocation().toString(), source.getLocation().getStartLine(), + source.toString(), kind diff --git a/python/ql/test/library-tests/taint/config/TestStep.ql b/python/ql/test/library-tests/taint/config/TestStep.ql index 2f702834d01..f16f2e36bb8 100644 --- a/python/ql/test/library-tests/taint/config/TestStep.ql +++ b/python/ql/test/library-tests/taint/config/TestStep.ql @@ -3,11 +3,8 @@ import semmle.python.security.TaintTracking import TaintLib import semmle.python.dataflow.Implementation - from TaintTrackingNode n, TaintTrackingNode s, TestConfig config where s = n.getASuccessor() and config = n.getConfiguration() -select - config + ":", - n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - " --> ", - s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), s.getContext() +select config + ":", n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), + n.getContext(), " --> ", s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), + s.getContext() diff --git a/python/ql/test/library-tests/taint/dataflow/Config.qll b/python/ql/test/library-tests/taint/dataflow/Config.qll index 3d077f8c5b4..34a36dd9e1f 100644 --- a/python/ql/test/library-tests/taint/dataflow/Config.qll +++ b/python/ql/test/library-tests/taint/dataflow/Config.qll @@ -2,7 +2,6 @@ import python import semmle.python.dataflow.DataFlow class TestConfiguration extends DataFlow::Configuration { - TestConfiguration() { this = "Test configuration" } override predicate isSource(ControlFlowNode source) { source.(NameNode).getId() = "SOURCE" } @@ -13,5 +12,4 @@ class TestConfiguration extends DataFlow::Configuration { sink = call.getAnArg() ) } - } diff --git a/python/ql/test/library-tests/taint/dataflow/Dataflow.ql b/python/ql/test/library-tests/taint/dataflow/Dataflow.ql index d758f32b2df..ced8b9a7c25 100644 --- a/python/ql/test/library-tests/taint/dataflow/Dataflow.ql +++ b/python/ql/test/library-tests/taint/dataflow/Dataflow.ql @@ -1,4 +1,3 @@ - import python import Config diff --git a/python/ql/test/library-tests/taint/dataflow/TestNode.ql b/python/ql/test/library-tests/taint/dataflow/TestNode.ql index 81bb0c0fc56..3498d5546da 100644 --- a/python/ql/test/library-tests/taint/dataflow/TestNode.ql +++ b/python/ql/test/library-tests/taint/dataflow/TestNode.ql @@ -2,4 +2,5 @@ import python import Config from TaintedNode n -select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext() diff --git a/python/ql/test/library-tests/taint/example/DilbertConfig.qll b/python/ql/test/library-tests/taint/example/DilbertConfig.qll index 1628fcc394f..c54ea8060a3 100644 --- a/python/ql/test/library-tests/taint/example/DilbertConfig.qll +++ b/python/ql/test/library-tests/taint/example/DilbertConfig.qll @@ -1,6 +1,6 @@ /** * @kind path-problem - * + * * An example configuration. * See ExampleConfiguration.expected for the results of running this query. */ @@ -9,23 +9,16 @@ import python import semmle.python.dataflow.Configuration /* First of all we set up some TaintKinds */ - class Engineer extends TaintKind { - Engineer() { this = "Wally" or this = "Dilbert" } - } class Wally extends Engineer { - Wally() { this = "Wally" } - } /** Then the configuration */ - class DilbertConfig extends TaintTracking::Configuration { - DilbertConfig() { this = "Dilbert config" } override predicate isSource(DataFlow::Node node, TaintKind kind) { @@ -46,11 +39,8 @@ class DilbertConfig extends TaintTracking::Configuration { /* Even the conscientious stop work if the building is on fire */ function_param("fire", node) } - } - - /** Helper predicate looking for `funcname(..., arg, ...)` */ private predicate function_param(string funcname, DataFlow::Node arg) { exists(Call call | diff --git a/python/ql/test/library-tests/taint/example/Edges.ql b/python/ql/test/library-tests/taint/example/Edges.ql index 4b975666d92..0674f3a073c 100644 --- a/python/ql/test/library-tests/taint/example/Edges.ql +++ b/python/ql/test/library-tests/taint/example/Edges.ql @@ -3,18 +3,24 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import DilbertConfig - string shortString(TaintTrackingNode n) { - if n.getContext().isTop() then - result = n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + " = " + n.getTaintKind() + if n.getContext().isTop() + then + result = + n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + + " = " + n.getTaintKind() else - result = n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + " = " + n.getTaintKind() + " (" + n.getContext().toString() + ")" + result = + n.getLocation().getStartLine() + ": " + n.getNode().toString() + n.getPath().extension() + + " = " + n.getTaintKind() + " (" + n.getContext().toString() + ")" } bindingset[s, len] string ljust(string s, int len) { - result = s + - " ".prefix(len-s.length()) + result = + s + + " " + .prefix(len - s.length()) } bindingset[s, len] @@ -23,7 +29,7 @@ string format(string s, int len) { s = "" and label = "[dataflow]" or s != "" and label = s - | + | result = ljust(label, len) ) } @@ -31,4 +37,3 @@ string format(string s, int len) { from TaintTrackingNode p, TaintTrackingNode s, string label where any(DilbertConfig config).(TaintTrackingImplementation).flowStep(p, s, label) select format(shortString(p), 50), format(label, 10), shortString(s) - diff --git a/python/ql/test/library-tests/taint/example/ExampleConfig.ql b/python/ql/test/library-tests/taint/example/ExampleConfig.ql index cb0c43de3d1..e3809c7a024 100644 --- a/python/ql/test/library-tests/taint/example/ExampleConfig.ql +++ b/python/ql/test/library-tests/taint/example/ExampleConfig.ql @@ -1,6 +1,6 @@ /** * @kind path-problem - * + * * An example configuration. * See ExampleConfiguration.expected for the results of running this query. */ @@ -9,7 +9,7 @@ import python import DilbertConfig import semmle.python.security.Paths - from DilbertConfig config, TaintedPathSource src, TaintedPathSink sink where config.hasFlowPath(src, sink) -select sink.getSink(), src, sink, "$@ goes to a $@.", src.getNode(), src.getTaintKind().toString(), sink.getNode(), "meeting" +select sink.getSink(), src, sink, "$@ goes to a $@.", src.getNode(), src.getTaintKind().toString(), + sink.getNode(), "meeting" diff --git a/python/ql/test/library-tests/taint/example/Nodes.ql b/python/ql/test/library-tests/taint/example/Nodes.ql index 21e315bca74..0a5ff02c2a3 100644 --- a/python/ql/test/library-tests/taint/example/Nodes.ql +++ b/python/ql/test/library-tests/taint/example/Nodes.ql @@ -3,8 +3,7 @@ import semmle.python.security.TaintTracking import semmle.python.dataflow.Implementation import DilbertConfig - from TaintTrackingNode n where n.getConfiguration() instanceof DilbertConfig -select n.getLocation().toString(), n.getNode().toString(), n.getPath().toString(), n.getContext().toString(), n.getTaintKind() - +select n.getLocation().toString(), n.getNode().toString(), n.getPath().toString(), + n.getContext().toString(), n.getTaintKind() diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected b/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected index 98b1ceba4e4..4ee4e15cefd 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected +++ b/python/ql/test/library-tests/taint/exception_traceback/TestNode.expected @@ -1,4 +1,4 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:8,43-50) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:7,43-50) | test.py:10:11:10:47 | test.py:10 | MyException() | exception.kind | | test.py:15:25:15:25 | test.py:15 | e | exception.kind | | test.py:16:13:16:34 | test.py:16 | Attribute() | exception.info | diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql b/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql index b9ec3c2ff3e..b11ef5e18e8 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestNode.ql @@ -1,8 +1,7 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse from TaintedNode node where not node.getLocation().getFile().inStdlib() -select node.getLocation(), node.getNode().getNode().toString(), node.getTaintKind() \ No newline at end of file +select node.getLocation(), node.getNode().getNode().toString(), node.getTaintKind() diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql b/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql index 8e625641b77..d66d80dae40 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestSource.ql @@ -1,11 +1,9 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse - from TaintSource src, TaintKind kind -where - src.isSourceOf(kind) and +where + src.isSourceOf(kind) and not src.getLocation().getFile().inStdlib() -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind \ No newline at end of file +select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql b/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql index 8354e2526f5..6d10a7c5ed3 100644 --- a/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql +++ b/python/ql/test/library-tests/taint/exception_traceback/TestStep.ql @@ -1,5 +1,4 @@ import python - import semmle.python.security.Exceptions import semmle.python.web.HttpResponse @@ -8,7 +7,6 @@ where s = n.getASuccessor() and not n.getLocation().getFile().inStdlib() and not s.getLocation().getFile().inStdlib() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getNode().toString(), s.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().toString(), + n.getContext(), " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), + s.getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll index 9cbbc6f9e2d..bc0534df455 100644 --- a/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll +++ b/python/ql/test/library-tests/taint/extensions/ExtensionsLib.qll @@ -1,17 +1,11 @@ import python - import semmle.python.security.TaintTracking class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -21,27 +15,17 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof SimpleTest - } - + override predicate sinks(TaintKind taint) { taint instanceof SimpleTest } } class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof SimpleTest - } - - override string toString() { - result = "simple.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof SimpleTest } + override string toString() { result = "simple.source" } } - predicate visit_call(CallNode call, FunctionObject func) { exists(AttrNode attr, ClassObject cls, string name | name.prefix(6) = "visit_" and @@ -52,9 +36,7 @@ predicate visit_call(CallNode call, FunctionObject func) { } /* Test call extensions by tracking taint through visitor methods */ - class TestCallReturnExtension extends DataFlowExtension::DataFlowNode { - TestCallReturnExtension() { exists(PyFunctionObject func | visit_call(_, func) and @@ -69,11 +51,9 @@ class TestCallReturnExtension extends DataFlowExtension::DataFlowNode { result = call ) } - } class TestCallParameterExtension extends DataFlowExtension::DataFlowNode { - TestCallParameterExtension() { exists(PyFunctionObject func, CallNode call | visit_call(call, func) and @@ -86,9 +66,8 @@ class TestCallParameterExtension extends DataFlowExtension::DataFlowNode { visit_call(call, func) and exists(int n | this = call.getArg(n) and - result.getNode() = func.getFunction().getArg(n+1) + result.getNode() = func.getFunction().getArg(n + 1) ) ) } - } diff --git a/python/ql/test/library-tests/taint/extensions/TestNode.expected b/python/ql/test/library-tests/taint/extensions/TestNode.expected index 71a89d1792c..ac67500eb3e 100644 --- a/python/ql/test/library-tests/taint/extensions/TestNode.expected +++ b/python/ql/test/library-tests/taint/extensions/TestNode.expected @@ -1,4 +1,4 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:7,77-84) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestNode.ql:5,77-84) | Taint simple.test | visitor.py:10 | arg | p2 = simple.test | | Taint simple.test | visitor.py:13 | arg | p2 = simple.test | | Taint simple.test | visitor.py:18 | arg | | diff --git a/python/ql/test/library-tests/taint/extensions/TestNode.ql b/python/ql/test/library-tests/taint/extensions/TestNode.ql index 842c63186ba..2fa17776be3 100644 --- a/python/ql/test/library-tests/taint/extensions/TestNode.ql +++ b/python/ql/test/library-tests/taint/extensions/TestNode.ql @@ -1,8 +1,6 @@ import python - import ExtensionsLib - from TaintedNode n -select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext() - +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext() diff --git a/python/ql/test/library-tests/taint/extensions/TestStep.expected b/python/ql/test/library-tests/taint/extensions/TestStep.expected index da27b3caf9e..c5915950d98 100644 --- a/python/ql/test/library-tests/taint/extensions/TestStep.expected +++ b/python/ql/test/library-tests/taint/extensions/TestStep.expected @@ -1,5 +1,5 @@ -WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:9,74-81) -WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:11,74-81) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:6,77-84) +WARNING: Predicate getNode has been deprecated and may be removed in future (TestStep.ql:8,17-24) | Taint simple.test | visitor.py:10 | arg | p2 = simple.test | --> | Taint simple.test | visitor.py:13 | arg | p2 = simple.test | | Taint simple.test | visitor.py:18 | arg | | --> | Taint simple.test | visitor.py:19 | arg | | | Taint simple.test | visitor.py:19 | arg | | --> | Taint simple.test | visitor.py:26 | Attribute() | | diff --git a/python/ql/test/library-tests/taint/extensions/TestStep.ql b/python/ql/test/library-tests/taint/extensions/TestStep.ql index 95003b44270..9005aba858e 100644 --- a/python/ql/test/library-tests/taint/extensions/TestStep.ql +++ b/python/ql/test/library-tests/taint/extensions/TestStep.ql @@ -1,11 +1,8 @@ import python - import ExtensionsLib - from TaintedNode n, TaintedNode s where s = n.getASuccessor() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getNode().getNode().toString(), s.getContext() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getNode().getNode().toString(), + n.getContext(), " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), + s.getNode().getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/general/Contexts.expected b/python/ql/test/library-tests/taint/general/Contexts.expected index f07c1452c6e..cfce11fbaa9 100644 --- a/python/ql/test/library-tests/taint/general/Contexts.expected +++ b/python/ql/test/library-tests/taint/general/Contexts.expected @@ -1,5 +1,5 @@ -WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:6,6-17) -WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:7,14-25) +WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:5,6-17) +WARNING: Type CallContext has been deprecated and may be removed in future (Contexts.ql:7,12-23) | assignment.py:1 | p0 = simple.test | Function test | | assignment.py:1 | p1 = simple.test | Function test | | assignment.py:1 | p2 = simple.test | Function test | diff --git a/python/ql/test/library-tests/taint/general/Contexts.ql b/python/ql/test/library-tests/taint/general/Contexts.ql index 9d3d7ec6c32..6eee5f449b2 100644 --- a/python/ql/test/library-tests/taint/general/Contexts.ql +++ b/python/ql/test/library-tests/taint/general/Contexts.ql @@ -1,10 +1,9 @@ - import python import semmle.python.dataflow.Implementation import TaintLib from CallContext context, Scope s -where exists(CallContext caller | caller.getCallee(_) = context) and -context.appliesToScope(s) +where + exists(CallContext caller | caller.getCallee(_) = context) and + context.appliesToScope(s) select s.getLocation().toString(), context, s.toString() - diff --git a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql index 25831de268d..6a4349b4100 100644 --- a/python/ql/test/library-tests/taint/general/ModuleAttribute.ql +++ b/python/ql/test/library-tests/taint/general/ModuleAttribute.ql @@ -2,8 +2,6 @@ import python import semmle.python.dataflow.Implementation import TaintLib - from ModuleValue m, string name, TaintedNode origin, TaintTrackingImplementation impl where impl.moduleAttributeTainted(m, name, origin) - select m.toString(), name, origin.toString(), origin.getContext(), origin.getLocation().toString() diff --git a/python/ql/test/library-tests/taint/general/ParamSource.ql b/python/ql/test/library-tests/taint/general/ParamSource.ql index 664fd8b77e5..f0956d0333d 100644 --- a/python/ql/test/library-tests/taint/general/ParamSource.ql +++ b/python/ql/test/library-tests/taint/general/ParamSource.ql @@ -1,37 +1,26 @@ import python import semmle.python.security.TaintTracking - /* Standard library sink */ import semmle.python.security.injection.Command class TestKind extends TaintKind { - TestKind() { - this = "test" - } - + TestKind() { this = "test" } } class CustomSource extends TaintSource { - CustomSource() { - exists(Parameter p | + exists(Parameter p | p.asName().getId() = "arg" and this.(ControlFlowNode).getNode() = p ) } - override predicate isSourceOf(TaintKind kind) { - kind instanceof TestKind - } - - override string toString() { - result = "Source of untrusted input" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof TestKind } + override string toString() { result = "Source of untrusted input" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -41,13 +30,10 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof TestKind - } - + override predicate sinks(TaintKind taint) { taint instanceof TestKind } } from TaintSource src, TaintSink sink, TaintKind srckind, TaintKind sinkkind - where src.flowsToSink(srckind, sink) and sink.sinks(sinkkind) -select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), sink.(ControlFlowNode).getNode().toString(), sinkkind +select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), + sink.(ControlFlowNode).getNode().toString(), sinkkind diff --git a/python/ql/test/library-tests/taint/general/TaintLib.qll b/python/ql/test/library-tests/taint/general/TaintLib.qll index b3984b32976..9e4cbc31a89 100644 --- a/python/ql/test/library-tests/taint/general/TaintLib.qll +++ b/python/ql/test/library-tests/taint/general/TaintLib.qll @@ -1,17 +1,11 @@ import python import semmle.python.security.TaintTracking - class SimpleTest extends TaintKind { - - SimpleTest() { - this = "simple.test" - } - + SimpleTest() { this = "simple.test" } } class SimpleSink extends TaintSink { - override string toString() { result = "Simple sink" } SimpleSink() { @@ -21,31 +15,21 @@ class SimpleSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof SimpleTest - } - + override predicate sinks(TaintKind taint) { taint instanceof SimpleTest } } class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof SimpleTest - } - - override string toString() { - result = "simple.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof SimpleTest } + override string toString() { result = "simple.source" } } class SimpleSanitizer extends Sanitizer { - SimpleSanitizer() { this = "Simple sanitizer" } - override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { + override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) { node.(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and taint instanceof SimpleTest } @@ -60,21 +44,16 @@ class SimpleSanitizer extends Sanitizer { } class BasicCustomTaint extends TaintKind { - - BasicCustomTaint() { - this = "basic.custom" - } + BasicCustomTaint() { this = "basic.custom" } override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) { tonode.(CallNode).getAnArg() = fromnode and tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and result = this } - } class BasicCustomSink extends TaintSink { - override string toString() { result = "Basic custom sink" } BasicCustomSink() { @@ -84,32 +63,21 @@ class BasicCustomSink extends TaintSink { ) } - override predicate sinks(TaintKind taint) { - taint instanceof BasicCustomTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof BasicCustomTaint } } - class BasicCustomSource extends TaintSource { - BasicCustomSource() { this.(NameNode).getId() = "CUSTOM_SOURCE" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof BasicCustomTaint - } - - override string toString() { - result = "basic.custom.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof BasicCustomTaint } + override string toString() { result = "basic.custom.source" } } class Rock extends TaintKind { - Rock() { this = "rock" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Scissors } @@ -119,31 +87,27 @@ class Rock extends TaintKind { call.getFunction().(NameNode).getId() = "paper" ) } - } class Paper extends TaintKind { - Paper() { this = "paper" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Rock } - predicate isSink(ControlFlowNode sink) { + predicate isSink(ControlFlowNode sink) { exists(CallNode call | call.getArg(0) = sink and call.getFunction().(NameNode).getId() = "scissors" ) } - } class Scissors extends TaintKind { - Scissors() { this = "scissors" } - override TaintKind getTaintOfMethodResult(string name) { + override TaintKind getTaintOfMethodResult(string name) { name = "prev" and result instanceof Paper } @@ -153,26 +117,18 @@ class Scissors extends TaintKind { call.getFunction().(NameNode).getId() = "rock" ) } - } class RockPaperScissorSource extends TaintSource { - - RockPaperScissorSource() { - exists(string name | - this.(NameNode).getId() = name | + RockPaperScissorSource() { + exists(string name | this.(NameNode).getId() = name | name = "ROCK" or name = "PAPER" or name = "SCISSORS" ) } - override predicate isSourceOf(TaintKind kind) { - kind = this.(NameNode).getId().toLowerCase() - } - - override string toString() { - result = "rock.paper.scissors.source" - } + override predicate isSourceOf(TaintKind kind) { kind = this.(NameNode).getId().toLowerCase() } + override string toString() { result = "rock.paper.scissors.source" } } private predicate function_param(string funcname, ControlFlowNode arg) { @@ -183,17 +139,14 @@ private predicate function_param(string funcname, ControlFlowNode arg) { } class RockPaperScissorSink extends TaintSink { - RockPaperScissorSink() { - exists(string name | - function_param(name, this) | + exists(string name | function_param(name, this) | name = "rock" or name = "paper" or name = "scissors" ) } override predicate sinks(TaintKind taint) { - exists(string name | - function_param(name, this) | + exists(string name | function_param(name, this) | name = "paper" and taint = "rock" or name = "rock" and taint = "scissors" @@ -202,79 +155,49 @@ class RockPaperScissorSink extends TaintSink { ) } - override string toString() { - result = "rock.paper.scissors.sink" - } - + override string toString() { result = "rock.paper.scissors.sink" } } class TaintCarrier extends TaintKind { - TaintCarrier() { this = "explicit.carrier" } override TaintKind getTaintOfMethodResult(string name) { name = "get_taint" and result instanceof SimpleTest } - - } /* There is no sink for `TaintCarrier`. It is not "dangerous" in itself; it merely holds a `SimpleTest`. */ class TaintCarrierSource extends TaintSource { + TaintCarrierSource() { this.(NameNode).getId() = "TAINT_CARRIER_SOURCE" } - TaintCarrierSource() { - this.(NameNode).getId() = "TAINT_CARRIER_SOURCE" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintCarrier } - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintCarrier - } - - override string toString() { - result = "taint.carrier.source" - } + override string toString() { result = "taint.carrier.source" } } - /* Some more realistic examples */ - abstract class UserInput extends TaintKind { - bindingset[this] UserInput() { any() } - } class UserInputSource extends TaintSource { + UserInputSource() { this.(CallNode).getFunction().(NameNode).getId() = "user_input" } - UserInputSource() { - this.(CallNode).getFunction().(NameNode).getId() = "user_input" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof UserInput - } - - override string toString() { - result = "user.input.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof UserInput } + override string toString() { result = "user.input.source" } } class SqlInjectionTaint extends UserInput { - SqlInjectionTaint() { this = "SQL injection" } - } class CommandInjectionTaint extends UserInput { - CommandInjectionTaint() { this = "Command injection" } - } class SqlSanitizer extends Sanitizer { - SqlSanitizer() { this = "SQL sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -288,11 +211,9 @@ class SqlSanitizer extends Sanitizer { ) and taint instanceof SqlInjectionTaint } - } class CommandSanitizer extends Sanitizer { - CommandSanitizer() { this = "Command sanitizer" } /** Holds if `test` shows value to be untainted with `taint` */ @@ -304,11 +225,9 @@ class CommandSanitizer extends Sanitizer { ) and taint instanceof CommandInjectionTaint } - } class SqlQuery extends TaintSink { - SqlQuery() { exists(CallNode call | call.getFunction().(NameNode).getId() = "sql_query" and @@ -318,15 +237,10 @@ class SqlQuery extends TaintSink { override string toString() { result = "SQL query" } - override predicate sinks(TaintKind taint) { - taint instanceof SqlInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof SqlInjectionTaint } } - class OsCommand extends TaintSink { - OsCommand() { exists(CallNode call | call.getFunction().(NameNode).getId() = "os_command" and @@ -336,59 +250,31 @@ class OsCommand extends TaintSink { override string toString() { result = "OS command" } - override predicate sinks(TaintKind taint) { - taint instanceof CommandInjectionTaint - } - + override predicate sinks(TaintKind taint) { taint instanceof CommandInjectionTaint } } - class Falsey extends TaintKind { - Falsey() { this = "falsey" } - override boolean booleanValue() { - result = false - } - + override boolean booleanValue() { result = false } } -class FalseySource extends TaintSource { +class FalseySource extends TaintSource { + FalseySource() { this.(NameNode).getId() = "FALSEY" } - FalseySource() { - this.(NameNode).getId() = "FALSEY" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof Falsey - } - - override string toString() { - result = "falsey.source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof Falsey } + override string toString() { result = "falsey.source" } } class TaintIterable extends TaintKind { + TaintIterable() { this = "iterable.simple" } - TaintIterable() { - this = "iterable.simple" - } - - override TaintKind getTaintForIteration() { - result instanceof SimpleTest - } - + override TaintKind getTaintForIteration() { result instanceof SimpleTest } } class TaintIterableSource extends TaintSource { + TaintIterableSource() { this.(NameNode).getId() = "ITERABLE_SOURCE" } - TaintIterableSource() { - this.(NameNode).getId() = "ITERABLE_SOURCE" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TaintIterable - } - + override predicate isSourceOf(TaintKind kind) { kind instanceof TaintIterable } } diff --git a/python/ql/test/library-tests/taint/general/TaintSanity.ql b/python/ql/test/library-tests/taint/general/TaintSanity.ql index ddfa5a3af32..d07828e5947 100644 --- a/python/ql/test/library-tests/taint/general/TaintSanity.ql +++ b/python/ql/test/library-tests/taint/general/TaintSanity.ql @@ -3,24 +3,27 @@ import semmle.python.dataflow.TaintTracking import semmle.python.dataflow.Implementation import TaintLib -from TaintKind taint, TaintTrackingContext c, DataFlow::Node n, string what, TaintTrackingImplementation impl +from + TaintKind taint, TaintTrackingContext c, DataFlow::Node n, string what, + TaintTrackingImplementation impl where -not exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c) and -( - impl.flowStep(_, n, c, _, taint, _) and what = "missing node at end of step" + not exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c) and + ( + impl.flowStep(_, n, c, _, taint, _) and what = "missing node at end of step" + or + impl.flowSource(n, c, _, taint) and what = "missing node for source" + ) or - impl.flowSource(n, c, _, taint) and what = "missing node for source" -) -or -exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c - | - not impl.flowStep(_, n, c, _, taint, _) and - not impl.flowSource(n, c, _, taint) and what = "TaintedNode with no reason" - or - impl.flowStep(t, n, c, _, taint, _) and what = "step ends where it starts" - or - impl.flowStep(t, _, _, _, _, _) and not impl.flowStep(_, n, c, _, taint, _) and - not impl.flowSource(n, c, _, taint) and what = "No predecessor and not a source" -) - + exists(TaintedNode t | t.getTaintKind() = taint and t.getNode() = n and t.getContext() = c | + not impl.flowStep(_, n, c, _, taint, _) and + not impl.flowSource(n, c, _, taint) and + what = "TaintedNode with no reason" + or + impl.flowStep(t, n, c, _, taint, _) and what = "step ends where it starts" + or + impl.flowStep(t, _, _, _, _, _) and + not impl.flowStep(_, n, c, _, taint, _) and + not impl.flowSource(n, c, _, taint) and + what = "No predecessor and not a source" + ) select n.getLocation(), taint, c, n.toString(), what diff --git a/python/ql/test/library-tests/taint/general/TestDefn.ql b/python/ql/test/library-tests/taint/general/TestDefn.ql index e793d24649b..e2791bf2e72 100644 --- a/python/ql/test/library-tests/taint/general/TestDefn.ql +++ b/python/ql/test/library-tests/taint/general/TestDefn.ql @@ -1,8 +1,7 @@ import python import TaintLib - from EssaNodeDefinition defn, TaintedNode n where n.getNode().asVariable() = defn.getVariable() -select - defn.getLocation().toString(), defn.getRepresentation(), n.getLocation().toString(), "Taint " + n.toString(), defn.getDefiningNode().getNode().toString() +select defn.getLocation().toString(), defn.getRepresentation(), n.getLocation().toString(), + "Taint " + n.toString(), defn.getDefiningNode().getNode().toString() diff --git a/python/ql/test/library-tests/taint/general/TestSanitizers.ql b/python/ql/test/library-tests/taint/general/TestSanitizers.ql index 3dca04d581e..cee31378f7d 100644 --- a/python/ql/test/library-tests/taint/general/TestSanitizers.ql +++ b/python/ql/test/library-tests/taint/general/TestSanitizers.ql @@ -1,4 +1,3 @@ - import python import semmle.python.security.TaintTracking import TaintLib @@ -6,5 +5,3 @@ import TaintLib from Sanitizer s, TaintKind taint, PyEdgeRefinement test where s.sanitizingEdge(taint, test) select s, taint, test.getLocation().toString(), test.getRepresentation() - - diff --git a/python/ql/test/library-tests/taint/general/TestSink.ql b/python/ql/test/library-tests/taint/general/TestSink.ql index d0361cc204a..422527fbee2 100644 --- a/python/ql/test/library-tests/taint/general/TestSink.ql +++ b/python/ql/test/library-tests/taint/general/TestSink.ql @@ -3,6 +3,6 @@ import semmle.python.security.TaintTracking import TaintLib from TaintSource src, TaintSink sink, TaintKind srckind, TaintKind sinkkind - where src.flowsToSink(srckind, sink) and sink.sinks(sinkkind) -select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), sink.(ControlFlowNode).getNode().toString(), sinkkind +select srckind, src.getLocation().toString(), sink.getLocation().getStartLine(), + sink.(ControlFlowNode).getNode().toString(), sinkkind diff --git a/python/ql/test/library-tests/taint/general/TestSource.ql b/python/ql/test/library-tests/taint/general/TestSource.ql index ba064220bfb..d71bab289e0 100644 --- a/python/ql/test/library-tests/taint/general/TestSource.ql +++ b/python/ql/test/library-tests/taint/general/TestSource.ql @@ -2,7 +2,6 @@ import python import semmle.python.security.TaintTracking import TaintLib - from TaintSource src, TaintKind kind where src.isSourceOf(kind) select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/taint/general/TestStep.ql b/python/ql/test/library-tests/taint/general/TestStep.ql index 710b180501d..c6de9cad361 100644 --- a/python/ql/test/library-tests/taint/general/TestStep.ql +++ b/python/ql/test/library-tests/taint/general/TestStep.ql @@ -2,11 +2,7 @@ import python import semmle.python.security.TaintTracking import TaintLib - from TaintedNode n, TaintedNode s -where - s = n.getASuccessor() -select - n.toString(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), - "-->", +where s = n.getASuccessor() +select n.toString(), n.getLocation().toString(), n.getNode().toString(), n.getContext(), "-->", s.toString(), s.getLocation().toString(), s.getNode().toString(), s.getContext() diff --git a/python/ql/test/library-tests/taint/general/TestTaint.ql b/python/ql/test/library-tests/taint/general/TestTaint.ql index 3b8bf2b4bde..904cbbbded9 100644 --- a/python/ql/test/library-tests/taint/general/TestTaint.ql +++ b/python/ql/test/library-tests/taint/general/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/general/TestVar.ql b/python/ql/test/library-tests/taint/general/TestVar.ql index b90760f55ce..991d3cdbfa4 100644 --- a/python/ql/test/library-tests/taint/general/TestVar.ql +++ b/python/ql/test/library-tests/taint/general/TestVar.ql @@ -1,8 +1,7 @@ import python import TaintLib - from EssaVariable var, TaintedNode n where n.getNode().asVariable() = var -select - var.getDefinition().getLocation().toString(), var.getRepresentation(), n.getLocation().toString(), "Taint " + n.toString() +select var.getDefinition().getLocation().toString(), var.getRepresentation(), + n.getLocation().toString(), "Taint " + n.toString() diff --git a/python/ql/test/library-tests/taint/namedtuple/Taint.qll b/python/ql/test/library-tests/taint/namedtuple/Taint.qll index 9d19a54488c..580ed13f8f1 100644 --- a/python/ql/test/library-tests/taint/namedtuple/Taint.qll +++ b/python/ql/test/library-tests/taint/namedtuple/Taint.qll @@ -41,7 +41,5 @@ class TestConfig extends TaintTracking::Configuration { source instanceof DictSource } - override predicate isSink(TaintTracking::Sink sink) { - none() - } + override predicate isSink(TaintTracking::Sink sink) { none() } } diff --git a/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql b/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql +++ b/python/ql/test/library-tests/taint/namedtuple/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/strings/Taint.qll b/python/ql/test/library-tests/taint/strings/Taint.qll index d045534e0ef..6c39426d161 100644 --- a/python/ql/test/library-tests/taint/strings/Taint.qll +++ b/python/ql/test/library-tests/taint/strings/Taint.qll @@ -3,60 +3,34 @@ import semmle.python.security.TaintTracking import semmle.python.security.strings.Untrusted import semmle.python.security.Exceptions - class SimpleSource extends TaintSource { - SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringKind - } - - override string toString() { - result = "taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } + override string toString() { result = "taint source" } } class ListSource extends TaintSource { - ListSource() { this.(NameNode).getId() = "TAINTED_LIST" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringSequenceKind - } - - override string toString() { - result = "list taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind } + override string toString() { result = "list taint source" } } class DictSource extends TaintSource { - DictSource() { this.(NameNode).getId() = "TAINTED_DICT" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringDictKind - } - - override string toString() { - result = "dict taint source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind } + override string toString() { result = "dict taint source" } } - class ExceptionInfoSource extends TaintSource { - ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" } - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExceptionInfo - } - - override string toString() { - result = "Exception info source" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo } + override string toString() { result = "Exception info source" } } diff --git a/python/ql/test/library-tests/taint/strings/TestStep.ql b/python/ql/test/library-tests/taint/strings/TestStep.ql index abec09b20d6..e7c014f2eb2 100644 --- a/python/ql/test/library-tests/taint/strings/TestStep.ql +++ b/python/ql/test/library-tests/taint/strings/TestStep.ql @@ -2,12 +2,10 @@ import python import semmle.python.security.TaintTracking import Taint - from TaintedNode n, TaintedNode s -where n.getLocation().getFile().getShortName() = "test.py" and -s.getLocation().getFile().getShortName() = "test.py" and -s = n.getASuccessor() -select - "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext(), - " --> ", - "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getAstNode(), s.getContext() +where + n.getLocation().getFile().getShortName() = "test.py" and + s.getLocation().getFile().getShortName() = "test.py" and + s = n.getASuccessor() +select "Taint " + n.getTaintKind(), n.getLocation().toString(), n.getAstNode(), n.getContext(), + " --> ", "Taint " + s.getTaintKind(), s.getLocation().toString(), s.getAstNode(), s.getContext() diff --git a/python/ql/test/library-tests/taint/strings/TestTaint.ql b/python/ql/test/library-tests/taint/strings/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/strings/TestTaint.ql +++ b/python/ql/test/library-tests/taint/strings/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/taint/unpacking/TestTaint.ql b/python/ql/test/library-tests/taint/unpacking/TestTaint.ql index 92657b1fef9..8347bd25433 100644 --- a/python/ql/test/library-tests/taint/unpacking/TestTaint.ql +++ b/python/ql/test/library-tests/taint/unpacking/TestTaint.ql @@ -15,4 +15,5 @@ where taint_string = tainted.getTaintKind().toString() ) ) -select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), taint_string +select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(), + taint_string diff --git a/python/ql/test/library-tests/thrift/Child.ql b/python/ql/test/library-tests/thrift/Child.ql index 5645c53ddb0..ebe72889aad 100644 --- a/python/ql/test/library-tests/thrift/Child.ql +++ b/python/ql/test/library-tests/thrift/Child.ql @@ -1,4 +1,3 @@ - import external.Thrift from ThriftElement t, int n diff --git a/python/ql/test/library-tests/thrift/File.ql b/python/ql/test/library-tests/thrift/File.ql index e4f497dbd01..7d85dd40ca4 100644 --- a/python/ql/test/library-tests/thrift/File.ql +++ b/python/ql/test/library-tests/thrift/File.ql @@ -1,7 +1,4 @@ - import external.Thrift - from ThriftNamedElement t - -select t.getName(), t.getFile().getBaseName() \ No newline at end of file +select t.getName(), t.getFile().getBaseName() diff --git a/python/ql/test/library-tests/thrift/Function.ql b/python/ql/test/library-tests/thrift/Function.ql index ff891bd5ece..2161fd8ec8a 100644 --- a/python/ql/test/library-tests/thrift/Function.ql +++ b/python/ql/test/library-tests/thrift/Function.ql @@ -1,12 +1,10 @@ - import external.Thrift from ThriftFunction t, string n, ThriftElement x where -exists(int i | x = t.getArgument(i) and n = i.toString()) -or -x = t.getAThrows() and n = "throws" -or -x = t.getReturnType() and n = "returns" - -select t, n, x \ No newline at end of file + exists(int i | x = t.getArgument(i) and n = i.toString()) + or + x = t.getAThrows() and n = "throws" + or + x = t.getReturnType() and n = "returns" +select t, n, x diff --git a/python/ql/test/library-tests/thrift/References.ql b/python/ql/test/library-tests/thrift/References.ql index c6621b44e95..f40e6e0a74b 100644 --- a/python/ql/test/library-tests/thrift/References.ql +++ b/python/ql/test/library-tests/thrift/References.ql @@ -1,4 +1,3 @@ - import python import external.Thrift diff --git a/python/ql/test/library-tests/thrift/Service.ql b/python/ql/test/library-tests/thrift/Service.ql index 801379c6a2e..3f3b07e0bc0 100644 --- a/python/ql/test/library-tests/thrift/Service.ql +++ b/python/ql/test/library-tests/thrift/Service.ql @@ -1,6 +1,4 @@ - import external.Thrift - from ThriftService service, string name select service, name, service.getFunction(name) diff --git a/python/ql/test/library-tests/thrift/Test.ql b/python/ql/test/library-tests/thrift/Test.ql index 735b9ad0eae..d755d9f1d26 100644 --- a/python/ql/test/library-tests/thrift/Test.ql +++ b/python/ql/test/library-tests/thrift/Test.ql @@ -1,7 +1,5 @@ - import external.Thrift from string cls where any(ThriftElement t).getAQlClass() = cls select cls.prefix(6) - diff --git a/python/ql/test/library-tests/thrift/Value.ql b/python/ql/test/library-tests/thrift/Value.ql index 7cf83b1df65..b42ae96d6ca 100644 --- a/python/ql/test/library-tests/thrift/Value.ql +++ b/python/ql/test/library-tests/thrift/Value.ql @@ -1,5 +1,4 @@ - import external.Thrift from ThriftElement t -select t, t.getValue() \ No newline at end of file +select t, t.getValue() diff --git a/python/ql/test/library-tests/types/attributes/Test.ql b/python/ql/test/library-tests/types/attributes/Test.ql index a92064a2551..a012b0d3a15 100644 --- a/python/ql/test/library-tests/types/attributes/Test.ql +++ b/python/ql/test/library-tests/types/attributes/Test.ql @@ -2,5 +2,5 @@ import python from ClassObject cls, ClassObject start, string name, Object val where not name.substring(0, 2) = "__" and val = cls.lookupMro(start, name) -select -cls.getOrigin().getLocation().getStartLine(), cls.toString(), start.toString(), name, val.toString(), val.getOrigin().getLocation().getStartLine() \ No newline at end of file +select cls.getOrigin().getLocation().getStartLine(), cls.toString(), start.toString(), name, + val.toString(), val.getOrigin().getLocation().getStartLine() diff --git a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql index 6895020718e..6e023dcada5 100644 --- a/python/ql/test/library-tests/types/classattr/ClassAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/ClassAttribute.ql @@ -8,12 +8,11 @@ import python from ClassObject cls, string name, string kind where -not cls.isC() and -not name.matches("\\_\\_%\\_\\_") and -( - cls.hasAttribute(name) and kind = "has" - or - cls.declaresAttribute(name) and kind = "declares" -) -select cls.toString(), kind ,name - + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") and + ( + cls.hasAttribute(name) and kind = "has" + or + cls.declaresAttribute(name) and kind = "declares" + ) +select cls.toString(), kind, name diff --git a/python/ql/test/library-tests/types/classattr/ClassMember.ql b/python/ql/test/library-tests/types/classattr/ClassMember.ql index b76851dd43d..1357deb0da9 100644 --- a/python/ql/test/library-tests/types/classattr/ClassMember.ql +++ b/python/ql/test/library-tests/types/classattr/ClassMember.ql @@ -7,12 +7,12 @@ import python from ClassObject cls, string name, string kind, Object o -where -not cls.isC() and -not name.matches("\\_\\_%\\_\\_") and -( - o = cls.lookupAttribute(name) and kind = "has" - or - o = cls.declaredAttribute(name) and kind = "declares" -) +where + not cls.isC() and + not name.matches("\\_\\_%\\_\\_") and + ( + o = cls.lookupAttribute(name) and kind = "has" + or + o = cls.declaredAttribute(name) and kind = "declares" + ) select cls.toString(), kind, name, o.toString() diff --git a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql index cdfd29b8d91..26e9ad08c26 100644 --- a/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql +++ b/python/ql/test/library-tests/types/classattr/SpecialAttribute.ql @@ -1,14 +1,13 @@ - import python from ClassObject cls, string name, string kind, Object o -where -not cls.isC() and -name.matches("\\_\\_%\\_\\_") and -not o = theObjectType().lookupAttribute(name) and -( - o = cls.lookupAttribute(name) and kind = "has" - or - o = cls.declaredAttribute(name) and kind = "declares" -) +where + not cls.isC() and + name.matches("\\_\\_%\\_\\_") and + not o = theObjectType().lookupAttribute(name) and + ( + o = cls.lookupAttribute(name) and kind = "has" + or + o = cls.declaredAttribute(name) and kind = "declares" + ) select cls.toString(), kind, name, o.toString() diff --git a/python/ql/test/library-tests/types/classes/FailedInference.ql b/python/ql/test/library-tests/types/classes/FailedInference.ql index df5e2ccf14f..192cf696fbf 100644 --- a/python/ql/test/library-tests/types/classes/FailedInference.ql +++ b/python/ql/test/library-tests/types/classes/FailedInference.ql @@ -1,11 +1,6 @@ - import python import semmle.python.pointsto.PointsTo from ClassValue cls, string reason - -where -Types::failedInference(cls, reason) - +where Types::failedInference(cls, reason) select cls, reason - diff --git a/python/ql/test/library-tests/types/classes/duplicate_base.ql b/python/ql/test/library-tests/types/classes/duplicate_base.ql index 4f865754088..47e975c4560 100644 --- a/python/ql/test/library-tests/types/classes/duplicate_base.ql +++ b/python/ql/test/library-tests/types/classes/duplicate_base.ql @@ -1,7 +1,5 @@ - import python from ClassObject cls where cls.hasDuplicateBases() select cls.toString() - diff --git a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql index efa1f66b8d8..62be45dce8e 100644 --- a/python/ql/test/library-tests/types/exceptions/ExitRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/ExitRaises.ql @@ -2,5 +2,4 @@ import python from RaisingNode r, Scope s, ClassObject cls where r.viableExceptionalExit(s, cls) - select r.getLocation().getStartLine(), r, s.toString(), cls diff --git a/python/ql/test/library-tests/types/exceptions/Handles.ql b/python/ql/test/library-tests/types/exceptions/Handles.ql index 51ceba1a6fb..601f2632392 100644 --- a/python/ql/test/library-tests/types/exceptions/Handles.ql +++ b/python/ql/test/library-tests/types/exceptions/Handles.ql @@ -1,5 +1,3 @@ - - import python from ExceptFlowNode n, ClassObject cls diff --git a/python/ql/test/library-tests/types/exceptions/Impossible.ql b/python/ql/test/library-tests/types/exceptions/Impossible.ql index e215a7e96ca..69c658edba6 100644 --- a/python/ql/test/library-tests/types/exceptions/Impossible.ql +++ b/python/ql/test/library-tests/types/exceptions/Impossible.ql @@ -1,20 +1,19 @@ - - import python from RaisingNode r, ControlFlowNode n, string kind -where r.unlikelySuccessor(n) and -( - r.getATrueSuccessor() = n and kind = "true" - or - r.getAFalseSuccessor() = n and kind = "false" - or - r.getAnExceptionalSuccessor() = n and kind = "exceptional" - or - not r.getATrueSuccessor() = n and - not r.getAFalseSuccessor() = n and - not r.getAnExceptionalSuccessor() = n and - kind = "normal" - -) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), kind +where + r.unlikelySuccessor(n) and + ( + r.getATrueSuccessor() = n and kind = "true" + or + r.getAFalseSuccessor() = n and kind = "false" + or + r.getAnExceptionalSuccessor() = n and kind = "exceptional" + or + not r.getATrueSuccessor() = n and + not r.getAFalseSuccessor() = n and + not r.getAnExceptionalSuccessor() = n and + kind = "normal" + ) +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), kind diff --git a/python/ql/test/library-tests/types/exceptions/LineRaises.ql b/python/ql/test/library-tests/types/exceptions/LineRaises.ql index f1f51952d00..933eb8d59bb 100644 --- a/python/ql/test/library-tests/types/exceptions/LineRaises.ql +++ b/python/ql/test/library-tests/types/exceptions/LineRaises.ql @@ -1,13 +1,12 @@ - import python from RaisingNode r, string type -where +where type = r.getARaisedType().toString() or type = "Unknown" and r.raisesUnknownType() or not exists(r.getARaisedType()) and - not r.raisesUnknownType() and type = "None" - + not r.raisesUnknownType() and + type = "None" select r.getNode().getLocation().getStartLine(), type diff --git a/python/ql/test/library-tests/types/exceptions/Raises.ql b/python/ql/test/library-tests/types/exceptions/Raises.ql index b003fd03dfa..aa477f718a2 100644 --- a/python/ql/test/library-tests/types/exceptions/Raises.ql +++ b/python/ql/test/library-tests/types/exceptions/Raises.ql @@ -1,13 +1,12 @@ - import python from PyFunctionObject f, string type -where +where type = f.getARaisedType().toString() or type = "Unknown" and f.raisesUnknownType() or not exists(f.getARaisedType()) and - not f.raisesUnknownType() and type = "None" - -select f.toString(), type \ No newline at end of file + not f.raisesUnknownType() and + type = "None" +select f.toString(), type diff --git a/python/ql/test/library-tests/types/exceptions/Reraises.ql b/python/ql/test/library-tests/types/exceptions/Reraises.ql index 9edcdf57b4b..699eb325f8c 100644 --- a/python/ql/test/library-tests/types/exceptions/Reraises.ql +++ b/python/ql/test/library-tests/types/exceptions/Reraises.ql @@ -1,6 +1,4 @@ - import python from ReraisingNode r - -select r.getLocation().getStartLine(), r, r.getARaisedType().toString() \ No newline at end of file +select r.getLocation().getStartLine(), r, r.getARaisedType().toString() diff --git a/python/ql/test/library-tests/types/exceptions/Viable.ql b/python/ql/test/library-tests/types/exceptions/Viable.ql index 544b0a0d0b6..e28fa1a907c 100644 --- a/python/ql/test/library-tests/types/exceptions/Viable.ql +++ b/python/ql/test/library-tests/types/exceptions/Viable.ql @@ -1,7 +1,6 @@ - - import python from RaisingNode r, ControlFlowNode n, ClassObject ex where r.viableExceptionEdge(n, ex) -select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), n.getNode().toString(), ex.toString() +select r.getLocation().getStartLine(), n.getLocation().getStartLine(), r.getNode().toString(), + n.getNode().toString(), ex.toString() diff --git a/python/ql/test/library-tests/types/functions/Zope.ql b/python/ql/test/library-tests/types/functions/Zope.ql index 91b828b2ff2..ca1c1a0f596 100644 --- a/python/ql/test/library-tests/types/functions/Zope.ql +++ b/python/ql/test/library-tests/types/functions/Zope.ql @@ -1,4 +1,3 @@ - import python import semmle.python.libraries.Zope diff --git a/python/ql/test/library-tests/types/properties/Deleters.ql b/python/ql/test/library-tests/types/properties/Deleters.ql index e57f5917e6e..ad99ceb387d 100644 --- a/python/ql/test/library-tests/types/properties/Deleters.ql +++ b/python/ql/test/library-tests/types/properties/Deleters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getDeleter().toString() diff --git a/python/ql/test/library-tests/types/properties/Getters.ql b/python/ql/test/library-tests/types/properties/Getters.ql index 2d495ccfc2f..5f232858696 100644 --- a/python/ql/test/library-tests/types/properties/Getters.ql +++ b/python/ql/test/library-tests/types/properties/Getters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getGetter().toString() diff --git a/python/ql/test/library-tests/types/properties/PythonProperties.ql b/python/ql/test/library-tests/types/properties/PythonProperties.ql index 91281c321a0..858326d6ac0 100644 --- a/python/ql/test/library-tests/types/properties/PythonProperties.ql +++ b/python/ql/test/library-tests/types/properties/PythonProperties.ql @@ -1,5 +1,4 @@ import python -from PythonPropertyObject p - +from PythonPropertyObject p select p.toString() diff --git a/python/ql/test/library-tests/types/properties/Setters.ql b/python/ql/test/library-tests/types/properties/Setters.ql index 4e13e54db63..871e6f9145f 100644 --- a/python/ql/test/library-tests/types/properties/Setters.ql +++ b/python/ql/test/library-tests/types/properties/Setters.ql @@ -1,5 +1,4 @@ import python from PythonPropertyObject p - select p.toString(), p.getSetter().toString() diff --git a/python/ql/test/library-tests/variables/definitions/test.ql b/python/ql/test/library-tests/variables/definitions/test.ql index 9abee816b3a..a3f0fab8155 100644 --- a/python/ql/test/library-tests/variables/definitions/test.ql +++ b/python/ql/test/library-tests/variables/definitions/test.ql @@ -1,5 +1,4 @@ import python from DefinitionNode d - select d.getLocation().getStartLine(), d.getLocation().getStartColumn(), d.toString() diff --git a/python/ql/test/library-tests/variables/scopes/free.ql b/python/ql/test/library-tests/variables/scopes/free.ql index 1e15bb3a312..65789e76a52 100644 --- a/python/ql/test/library-tests/variables/scopes/free.ql +++ b/python/ql/test/library-tests/variables/scopes/free.ql @@ -1,7 +1,8 @@ import python from LocalVariable v, Scope inner -where v.escapes() and inner = v.getAnAccess().getScope() and -inner != v.getScope() +where + v.escapes() and + inner = v.getAnAccess().getScope() and + inner != v.getScope() select v.toString(), v.getScope().toString(), inner.toString() - diff --git a/python/ql/test/library-tests/variables/scopes/globals.ql b/python/ql/test/library-tests/variables/scopes/globals.ql index 8d200aa81b0..65e572c2ab4 100644 --- a/python/ql/test/library-tests/variables/scopes/globals.ql +++ b/python/ql/test/library-tests/variables/scopes/globals.ql @@ -2,4 +2,3 @@ import python from GlobalVariable l select l.toString(), l.getScope().toString() - diff --git a/python/ql/test/library-tests/variables/scopes/locals.ql b/python/ql/test/library-tests/variables/scopes/locals.ql index 264c5e9b7d1..62814925fe9 100644 --- a/python/ql/test/library-tests/variables/scopes/locals.ql +++ b/python/ql/test/library-tests/variables/scopes/locals.ql @@ -1,10 +1,8 @@ import python from LocalVariable l, string kind -where -l instanceof FastLocalVariable and kind = "fast" -or -l instanceof NameLocalVariable and kind = "name" - +where + l instanceof FastLocalVariable and kind = "fast" + or + l instanceof NameLocalVariable and kind = "name" select l, l.getScope(), kind - diff --git a/python/ql/test/library-tests/variables/scopes/lookup.ql b/python/ql/test/library-tests/variables/scopes/lookup.ql index c7a776c7caa..248cd62b911 100644 --- a/python/ql/test/library-tests/variables/scopes/lookup.ql +++ b/python/ql/test/library-tests/variables/scopes/lookup.ql @@ -2,15 +2,17 @@ import python from NameNode n, string l where -n.isLoad() and ( - n.isGlobal() and l = "global" - or - n.isLocal() and l = "local" - or - n.isNonLocal() and l = "non-local" - or - not n.isGlobal() and not n.isLocal() and - not n.isNonLocal() and - l = "none" -) + n.isLoad() and + ( + n.isGlobal() and l = "global" + or + n.isLocal() and l = "local" + or + n.isNonLocal() and l = "non-local" + or + not n.isGlobal() and + not n.isLocal() and + not n.isNonLocal() and + l = "none" + ) select n.getLocation().getStartLine(), n.toString(), l diff --git a/python/ql/test/library-tests/variables/scopes/scopes.ql b/python/ql/test/library-tests/variables/scopes/scopes.ql index b87a45c9939..b722b89e51e 100644 --- a/python/ql/test/library-tests/variables/scopes/scopes.ql +++ b/python/ql/test/library-tests/variables/scopes/scopes.ql @@ -1,4 +1,3 @@ - import python from Variable v, Scope s diff --git a/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/requests/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/six/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql b/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql index cbeed6c2e4b..52fd7ff218e 100644 --- a/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql +++ b/python/ql/test/library-tests/web/client/stdlib/ClientHttpRequests.ql @@ -1,11 +1,7 @@ import python - import semmle.python.web.Http import semmle.python.web.ClientHttpRequest from Client::HttpRequest req, string method -where - if exists(req.getMethodUpper()) - then method = req.getMethodUpper() - else method = "" +where if exists(req.getMethodUpper()) then method = req.getMethodUpper() else method = "" select req, req.getAUrlPart(), method diff --git a/python/ql/test/qlpack.yml b/python/ql/test/qlpack.yml index eed82a82aec..afae7523793 100644 --- a/python/ql/test/qlpack.yml +++ b/python/ql/test/qlpack.yml @@ -1,3 +1,4 @@ name: codeql-python-tests version: 0.0.0 libraryPathDependencies: codeql-python +extractor: python diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected index cf89ddfc44f..4bdb1134776 100644 --- a/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected +++ b/python/ql/test/query-tests/Classes/Arguments/WrongNameForArgumentInClassInstantiation.expected @@ -1,4 +1,4 @@ -| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function __init__ | F2.__init__ | -| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | +| wrong_arguments.py:65:1:65:7 | F0() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:66:1:66:7 | F1() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:67:1:67:12 | F2() | Keyword argument 'y' is not a supported parameter name of $@. | wrong_arguments.py:12:5:12:30 | Function F2.__init__ | F2.__init__ | +| wrong_arguments.py:92:1:92:27 | F6() | Keyword argument 'z' is not a supported parameter name of $@. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | diff --git a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected index b0c156dc867..f0df1fe58c9 100644 --- a/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected +++ b/python/ql/test/query-tests/Classes/Arguments/WrongNumberArgumentsInClassInstantiation.expected @@ -1,15 +1,15 @@ -| wrong_arguments.py:37:1:37:4 | F0() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:38:1:38:4 | F1() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:39:1:39:4 | F2() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:12:5:12:30 | Function __init__ | F2.__init__ | -| wrong_arguments.py:40:1:40:4 | F3() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:16:5:16:40 | Function __init__ | F3.__init__ | -| wrong_arguments.py:41:1:41:4 | F4() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:20:5:20:31 | Function __init__ | F4.__init__ | -| wrong_arguments.py:42:1:42:4 | F5() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:24:5:24:42 | Function __init__ | F5.__init__ | -| wrong_arguments.py:43:1:43:5 | F6() | Call to $@ with too few arguments; should be no fewer than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:44:1:44:7 | F7() | Call to $@ with too few arguments; should be no fewer than 3. | wrong_arguments.py:32:5:32:33 | Function __init__ | F7.__init__ | -| wrong_arguments.py:48:1:48:7 | F0() | Call to $@ with too many arguments; should be no more than 1. | wrong_arguments.py:4:5:4:26 | Function __init__ | F0.__init__ | -| wrong_arguments.py:49:1:49:9 | F1() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:8:5:8:36 | Function __init__ | F1.__init__ | -| wrong_arguments.py:50:1:50:9 | F5() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:24:5:24:42 | Function __init__ | F5.__init__ | -| wrong_arguments.py:51:1:51:9 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:52:1:52:11 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:85:1:85:12 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | -| wrong_arguments.py:86:1:86:7 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function __init__ | F6.__init__ | +| wrong_arguments.py:37:1:37:4 | F0() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:38:1:38:4 | F1() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:39:1:39:4 | F2() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:12:5:12:30 | Function F2.__init__ | F2.__init__ | +| wrong_arguments.py:40:1:40:4 | F3() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:16:5:16:40 | Function F3.__init__ | F3.__init__ | +| wrong_arguments.py:41:1:41:4 | F4() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:20:5:20:31 | Function F4.__init__ | F4.__init__ | +| wrong_arguments.py:42:1:42:4 | F5() | Call to $@ with too few arguments; should be no fewer than 1. | wrong_arguments.py:24:5:24:42 | Function F5.__init__ | F5.__init__ | +| wrong_arguments.py:43:1:43:5 | F6() | Call to $@ with too few arguments; should be no fewer than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:44:1:44:7 | F7() | Call to $@ with too few arguments; should be no fewer than 3. | wrong_arguments.py:32:5:32:33 | Function F7.__init__ | F7.__init__ | +| wrong_arguments.py:48:1:48:7 | F0() | Call to $@ with too many arguments; should be no more than 1. | wrong_arguments.py:4:5:4:26 | Function F0.__init__ | F0.__init__ | +| wrong_arguments.py:49:1:49:9 | F1() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:8:5:8:36 | Function F1.__init__ | F1.__init__ | +| wrong_arguments.py:50:1:50:9 | F5() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:24:5:24:42 | Function F5.__init__ | F5.__init__ | +| wrong_arguments.py:51:1:51:9 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:52:1:52:11 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:85:1:85:12 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | +| wrong_arguments.py:86:1:86:7 | F6() | Call to $@ with too many arguments; should be no more than 2. | wrong_arguments.py:28:5:28:30 | Function F6.__init__ | F6.__init__ | diff --git a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected index 2393f18674a..5f0c2c4797c 100644 --- a/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected +++ b/python/ql/test/query-tests/Functions/general/IterReturnsNonIterator.expected @@ -1,4 +1,4 @@ -| file://:Compiled Code:0:0:0:0 | builtin-class object | Class object is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:16:5:16:23 | Function __iter__ | __iter__ | -| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:22:5:22:23 | Function __iter__ | __iter__ | -| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:27:5:27:23 | Function __iter__ | __iter__ | -| protocols.py:30:1:30:26 | class IteratorMissingIter | Class IteratorMissingIter is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:40:5:40:23 | Function __iter__ | __iter__ | +| file://:0:0:0:0 | builtin-class object | Class object is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:16:5:16:23 | Function X.__iter__ | __iter__ | +| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:22:5:22:23 | Function IteratorMissingNext.__iter__ | __iter__ | +| protocols.py:20:1:20:26 | class IteratorMissingNext | Class IteratorMissingNext is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:27:5:27:23 | Function IterableMissingNext.__iter__ | __iter__ | +| protocols.py:30:1:30:26 | class IteratorMissingIter | Class IteratorMissingIter is returned as an iterator (by $@) but does not fully implement the iterator interface. | protocols.py:40:5:40:23 | Function IterableMissingIter.__iter__ | __iter__ | diff --git a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected index 84c08d89426..2eff178d972 100644 --- a/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected +++ b/python/ql/test/query-tests/Functions/general/OverlyComplexDelMethod.expected @@ -1 +1 @@ -| protocols.py:74:5:74:22 | Function __del__ | Overly complex '__del__' method. | +| protocols.py:74:5:74:22 | Function MegaDel.__del__ | Overly complex '__del__' method. | diff --git a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected index f23936e6a42..81c45ab8abe 100644 --- a/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/general/SignatureOverriddenMethod.expected @@ -1,2 +1,2 @@ -| om_test.py:32:5:32:35 | Function grossly_wrong1 | Overriding method 'grossly_wrong1' has signature mismatch with $@. | om_test.py:12:5:12:41 | Function grossly_wrong1 | overridden method | -| om_test.py:35:5:35:47 | Function grossly_wrong2 | Overriding method 'grossly_wrong2' has signature mismatch with $@. | om_test.py:15:5:15:41 | Function grossly_wrong2 | overridden method | +| om_test.py:32:5:32:35 | Function Derived.grossly_wrong1 | Overriding method 'grossly_wrong1' has signature mismatch with $@. | om_test.py:12:5:12:41 | Function Base.grossly_wrong1 | overridden method | +| om_test.py:35:5:35:47 | Function Derived.grossly_wrong2 | Overriding method 'grossly_wrong2' has signature mismatch with $@. | om_test.py:15:5:15:41 | Function Base.grossly_wrong2 | overridden method | diff --git a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected index 527ad805604..3192999aad2 100644 --- a/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/overriding/IncorrectlySpecifiedOverriddenMethod.expected @@ -1,9 +1,9 @@ -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 | -| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 | -| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 | -| test.py:64:5:64:19 | Function meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function meth | method Correct2.meth | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 | +| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 | +| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 | +| test.py:64:5:64:19 | Function BlameBase.meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function Correct2.meth | method Correct2.meth | diff --git a/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected b/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected index 99f0fb667d6..bcb9363a55a 100644 --- a/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected +++ b/python/ql/test/query-tests/Functions/overriding/SignatureOverriddenMethod.expected @@ -1 +1 @@ -| test.py:30:5:30:26 | Function meth3 | Overriding method 'meth3' has signature mismatch with $@. | test.py:11:5:11:20 | Function meth3 | overridden method | +| test.py:30:5:30:26 | Function Derived.meth3 | Overriding method 'meth3' has signature mismatch with $@. | test.py:11:5:11:20 | Function Base.meth3 | overridden method | diff --git a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected index 60640bb96ba..c2a8e8ee573 100644 --- a/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected +++ b/python/ql/test/query-tests/Functions/return_values/ReturnValueIgnored.expected @@ -1,3 +1,3 @@ | functions_test.py:159:5:159:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:12:1:12:11 | Function ok2 | ok2 | | functions_test.py:160:5:160:9 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | functions_test.py:36:1:36:11 | Function ok4 | ok4 | -| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:Compiled Code:0:0:0:0 | Builtin-function sorted | sorted | +| functions_test.py:161:5:161:17 | ExprStmt | Call discards return value of function $@. The result is used in 80% of calls. | file://:0:0:0:0 | Builtin-function sorted | sorted | diff --git a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected index 163bcab7b3d..47bedf61d7c 100644 --- a/python/ql/test/query-tests/Imports/unused/UnusedImport.expected +++ b/python/ql/test/query-tests/Imports/unused/UnusedImport.expected @@ -1,3 +1,5 @@ +| import_structure_1.py:5:1:5:28 | Import | Import of 'bar' is not used. | +| import_structure_2.py:6:1:6:23 | Import | Import of 'bar' is not used. | | imports_test.py:2:1:2:23 | Import | Import of 'module2' is not used. | | imports_test.py:6:1:6:12 | Import | Import of 'cycle' is not used. | | imports_test.py:10:1:10:22 | Import | Import of 'top_level_cycle' is not used. | diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_1.py b/python/ql/test/query-tests/Imports/unused/import_structure_1.py new file mode 100644 index 00000000000..a76fe99f12c --- /dev/null +++ b/python/ql/test/query-tests/Imports/unused/import_structure_1.py @@ -0,0 +1,8 @@ +# there should be no difference whether you import 2 things on 1 line, or use 2 +# lines +from typing import Optional + +from unknown import foo, bar + + +var: Optional['foo'] = None diff --git a/python/ql/test/query-tests/Imports/unused/import_structure_2.py b/python/ql/test/query-tests/Imports/unused/import_structure_2.py new file mode 100644 index 00000000000..90d4255ba39 --- /dev/null +++ b/python/ql/test/query-tests/Imports/unused/import_structure_2.py @@ -0,0 +1,8 @@ +# there should be no difference whether you import 2 things on 1 line, or use 2 +# lines +from typing import Optional + +from unknown import foo +from unknown import bar + +var: Optional['foo'] = None diff --git a/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql b/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql index 545453e93eb..8525edcb8b8 100644 --- a/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql +++ b/python/ql/test/query-tests/Metrics/ratios/CodeRatio.ql @@ -1,7 +1,6 @@ - import python from Module m, ModuleMetrics mm where mm = m.getMetrics() and mm.getNumberOfLines() > 0 -select m, 100.0 * ((float)mm.getNumberOfLinesOfCode() / (float)mm.getNumberOfLines()) as ratio -order by ratio desc \ No newline at end of file +select m, 100.0 * (mm.getNumberOfLinesOfCode().(float) / mm.getNumberOfLines().(float)) as ratio + order by ratio desc diff --git a/python/ql/test/query-tests/Resources/Dataflow.ql b/python/ql/test/query-tests/Resources/Dataflow.ql index ee92ee981c3..4e2cf15b50d 100644 --- a/python/ql/test/query-tests/Resources/Dataflow.ql +++ b/python/ql/test/query-tests/Resources/Dataflow.ql @@ -1,16 +1,14 @@ - import python import Resources.FileOpen - from EssaVariable v, EssaDefinition def, string open, string exit -where def = v.getDefinition() and v.getSourceVariable().getName().charAt(0) = "f" and -( - var_is_open(v, _) and open = "open" - or - not var_is_open(v, _) and open = "closed" -) -and -if BaseFlow::reaches_exit(v) then exit = "exit" else exit = "" - +where + def = v.getDefinition() and + v.getSourceVariable().getName().charAt(0) = "f" and + ( + var_is_open(v, _) and open = "open" + or + not var_is_open(v, _) and open = "closed" + ) and + if BaseFlow::reaches_exit(v) then exit = "exit" else exit = "" select v.getRepresentation() + " = " + v.getDefinition().getRepresentation(), open, exit diff --git a/python/ql/test/query-tests/Security/CWE-327/TestNode.ql b/python/ql/test/query-tests/Security/CWE-327/TestNode.ql index 046378e4ea1..50305f21a2e 100644 --- a/python/ql/test/query-tests/Security/CWE-327/TestNode.ql +++ b/python/ql/test/query-tests/Security/CWE-327/TestNode.ql @@ -1,6 +1,5 @@ import python import semmle.python.security.TaintTracking - import python import semmle.python.security.SensitiveData import semmle.python.security.Crypto