mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Merge remote-tracking branch 'upstream/master' into DefaultTaintTracking-Configuration
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -19,5 +19,6 @@
|
|||||||
|
|
||||||
# It's useful (though not required) to be able to unpack codeql in the ql checkout itself
|
# It's useful (though not required) to be able to unpack codeql in the ql checkout itself
|
||||||
/codeql/
|
/codeql/
|
||||||
.vscode/settings.json
|
|
||||||
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
csharp/extractor/Semmle.Extraction.CSharp.Driver/Properties/launchSettings.json
|
||||||
|
.vscode
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Contributing to CodeQL
|
# 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).
|
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.
|
- 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.
|
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).
|
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
|
CLA agreements. Under GDPR legislation, we do this
|
||||||
on the basis of our legitimate interest in creating the CodeQL product.
|
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.
|
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.
|
|
||||||
|
|||||||
13
COPYRIGHT
13
COPYRIGHT
@@ -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.
|
|
||||||
189
LICENSE
189
LICENSE
@@ -1,176 +1,21 @@
|
|||||||
Apache License
|
MIT License
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
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,
|
The above copyright notice and this permission notice shall be included in all
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
the copyright owner that is granting the License.
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
other entities that control, are controlled by, or are under common
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
control with that entity. For the purposes of this definition,
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
SOFTWARE.
|
||||||
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
|
|
||||||
|
|||||||
@@ -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`. |
|
| 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`. |
|
| 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. |
|
| 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
|
## 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.
|
* [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()`.
|
* 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`.
|
* `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
|
## Changes to autobuilder
|
||||||
|
|||||||
@@ -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. |
|
| 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. |
|
| 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. |
|
| 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 more variations of URL scheme checks. |
|
||||||
|
|
||||||
## Changes to libraries
|
## Changes to libraries
|
||||||
|
|
||||||
|
|||||||
4
cpp/ql/src/codeql-suites/cpp-code-scanning.qls
Normal file
4
cpp/ql/src/codeql-suites/cpp-code-scanning.qls
Normal file
@@ -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
|
||||||
@@ -152,6 +152,16 @@
|
|||||||
| stl.cpp:105:2:105:4 | ss1 [post update] | stl.cpp:110:7:110: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:109:7:109:9 | ss2 | |
|
||||||
| stl.cpp:106:2:106:4 | ss2 [post update] | stl.cpp:111:7:111: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: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:5:8:5:13 | clean1 | |
|
||||||
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |
|
| taint.cpp:4:40:4:45 | clean1 | taint.cpp:6:3:6:8 | clean1 | |
|
||||||
|
|||||||
@@ -110,3 +110,24 @@ void test_stringstream_int(int source)
|
|||||||
sink(ss1.str());
|
sink(ss1.str());
|
||||||
sink(ss2.str()); // tainted [NOT DETECTED]
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@
|
|||||||
| stl.cpp:71:7:71:7 | a | 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 |
|
||||||
| stl.cpp:73:7:73:7 | c | stl.cpp:69:16:69:21 | 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: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: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: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 |
|
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
| format.cpp:106:8:106:14 | format.cpp:105:38:105:52 | 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: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: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: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: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 |
|
| taint.cpp:43:7:43:13 | taint.cpp:37:22:37:27 | AST only |
|
||||||
|
|||||||
@@ -341,6 +341,8 @@ namespace Semmle.Extraction.Tests
|
|||||||
string cwd = @"C:\Project")
|
string cwd = @"C:\Project")
|
||||||
{
|
{
|
||||||
Actions.GetEnvironmentVariable["CODEQL_AUTOBUILDER_CSHARP_NO_INDEXING"] = "false";
|
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_EXTRACTOR_CSHARP_ROOT"] = @"C:\codeql\csharp";
|
||||||
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
|
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
|
||||||
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";
|
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";
|
||||||
@@ -364,8 +366,7 @@ namespace Semmle.Extraction.Tests
|
|||||||
Actions.GetCurrentDirectory = cwd;
|
Actions.GetCurrentDirectory = cwd;
|
||||||
Actions.IsWindows = isWindows;
|
Actions.IsWindows = isWindows;
|
||||||
|
|
||||||
var options = new AutobuildOptions();
|
var options = new AutobuildOptions(Actions);
|
||||||
options.ReadEnvironment(Actions);
|
|
||||||
return new Autobuilder(Actions, options);
|
return new Autobuilder(Actions, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,9 @@
|
|||||||
{
|
{
|
||||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||||
{
|
{
|
||||||
(var javaHome, var dist) =
|
var javaHome = builder.JavaHome;
|
||||||
builder.CodeQLJavaHome != null ?
|
var dist = builder.Distribution;
|
||||||
(builder.CodeQLJavaHome, builder.CodeQLExtractorCSharpRoot) :
|
|
||||||
(builder.SemmleJavaHome, builder.SemmleDist);
|
|
||||||
var command = new CommandBuilder(builder.Actions).
|
var command = new CommandBuilder(builder.Actions).
|
||||||
RunCommand(builder.Actions.PathCombine(javaHome, "bin", "java")).
|
RunCommand(builder.Actions.PathCombine(javaHome, "bin", "java")).
|
||||||
Argument("-jar").
|
Argument("-jar").
|
||||||
|
|||||||
@@ -10,40 +10,40 @@ namespace Semmle.Autobuild
|
|||||||
public class AutobuildOptions
|
public class AutobuildOptions
|
||||||
{
|
{
|
||||||
public readonly int SearchDepth = 3;
|
public readonly int SearchDepth = 3;
|
||||||
public string RootDirectory = null;
|
public readonly string RootDirectory;
|
||||||
static readonly string prefix = "LGTM_INDEX_";
|
private const string prefix = "LGTM_INDEX_";
|
||||||
|
|
||||||
public string VsToolsVersion;
|
public readonly string? VsToolsVersion;
|
||||||
public string MsBuildArguments;
|
public readonly string? MsBuildArguments;
|
||||||
public string MsBuildPlatform;
|
public readonly string? MsBuildPlatform;
|
||||||
public string MsBuildConfiguration;
|
public readonly string? MsBuildConfiguration;
|
||||||
public string MsBuildTarget;
|
public readonly string? MsBuildTarget;
|
||||||
public string DotNetArguments;
|
public readonly string? DotNetArguments;
|
||||||
public string DotNetVersion;
|
public readonly string? DotNetVersion;
|
||||||
public string BuildCommand;
|
public readonly string? BuildCommand;
|
||||||
public string[] Solution;
|
public readonly string[] Solution;
|
||||||
|
|
||||||
public bool IgnoreErrors;
|
public readonly bool IgnoreErrors;
|
||||||
public bool Buildless;
|
public readonly bool Buildless;
|
||||||
public bool AllSolutions;
|
public readonly bool AllSolutions;
|
||||||
public bool NugetRestore;
|
public readonly bool NugetRestore;
|
||||||
|
|
||||||
public Language Language;
|
public readonly Language Language;
|
||||||
public bool Indexing;
|
public readonly bool Indexing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads options from environment variables.
|
/// Reads options from environment variables.
|
||||||
/// Throws ArgumentOutOfRangeException for invalid arguments.
|
/// Throws ArgumentOutOfRangeException for invalid arguments.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void ReadEnvironment(IBuildActions actions)
|
public AutobuildOptions(IBuildActions actions)
|
||||||
{
|
{
|
||||||
RootDirectory = actions.GetCurrentDirectory();
|
RootDirectory = actions.GetCurrentDirectory();
|
||||||
VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION");
|
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");
|
MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM");
|
||||||
MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION");
|
MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION");
|
||||||
MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET");
|
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");
|
DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION");
|
||||||
BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND");
|
BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND");
|
||||||
Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]);
|
Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]);
|
||||||
@@ -60,7 +60,7 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
public static class OptionsExtensions
|
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;
|
if (value == null) return defaultValue;
|
||||||
switch (value.ToLower())
|
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)
|
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)
|
if (value == null)
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ namespace Semmle.Autobuild
|
|||||||
BuildScript Analyse(Autobuilder builder, bool auto);
|
BuildScript Analyse(Autobuilder builder, bool auto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exception indicating that environment variables are missing or invalid.
|
||||||
|
/// </summary>
|
||||||
|
class InvalidEnvironmentException : Exception
|
||||||
|
{
|
||||||
|
public InvalidEnvironmentException(string m) : base(m) { }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main application logic, containing all data
|
/// Main application logic, containing all data
|
||||||
/// gathered from the project and filesystem.
|
/// gathered from the project and filesystem.
|
||||||
@@ -69,7 +77,7 @@ namespace Semmle.Autobuild
|
|||||||
/// List of project/solution files to build.
|
/// List of project/solution files to build.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IList<IProjectOrSolution> ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value;
|
public IList<IProjectOrSolution> ProjectsOrSolutionsToBuild => projectsOrSolutionsToBuildLazy.Value;
|
||||||
readonly Lazy<IList<IProjectOrSolution>> projectsOrSolutionsToBuildLazy;
|
private readonly Lazy<IList<IProjectOrSolution>> projectsOrSolutionsToBuildLazy;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Holds if a given path was found.
|
/// Holds if a given path was found.
|
||||||
@@ -129,7 +137,7 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
projectsOrSolutionsToBuildLazy = new Lazy<IList<IProjectOrSolution>>(() =>
|
projectsOrSolutionsToBuildLazy = new Lazy<IList<IProjectOrSolution>>(() =>
|
||||||
{
|
{
|
||||||
List<IProjectOrSolution> ret;
|
List<IProjectOrSolution>? ret;
|
||||||
if (options.Solution.Any())
|
if (options.Solution.Any())
|
||||||
{
|
{
|
||||||
ret = new List<IProjectOrSolution>();
|
ret = new List<IProjectOrSolution>();
|
||||||
@@ -143,7 +151,7 @@ namespace Semmle.Autobuild
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<IProjectOrSolution> FindFiles(string extension, Func<string, ProjectOrSolution> create)
|
IEnumerable<IProjectOrSolution>? FindFiles(string extension, Func<string, ProjectOrSolution> create)
|
||||||
{
|
{
|
||||||
var matchingFiles = GetExtensions(extension).
|
var matchingFiles = GetExtensions(extension).
|
||||||
Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)).
|
Select(p => (ProjectOrSolution: create(p.Item1), DistanceFromRoot: p.Item2)).
|
||||||
@@ -177,19 +185,34 @@ namespace Semmle.Autobuild
|
|||||||
});
|
});
|
||||||
|
|
||||||
CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT");
|
CodeQLExtractorCSharpRoot = Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_ROOT");
|
||||||
|
|
||||||
CodeQLJavaHome = Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME");
|
|
||||||
|
|
||||||
SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST");
|
SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST");
|
||||||
|
|
||||||
SemmleJavaHome = Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME");
|
|
||||||
|
|
||||||
SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS");
|
SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS");
|
||||||
|
|
||||||
if (CodeQLExtractorCSharpRoot == null && SemmleDist == null)
|
JavaHome =
|
||||||
Log(Severity.Error, "The environment variables CODEQL_EXTRACTOR_CSHARP_ROOT and SEMMLE_DIST have not been set.");
|
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);
|
readonly ILogger logger = new ConsoleLogger(Verbosity.Info);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -271,9 +294,9 @@ namespace Semmle.Autobuild
|
|||||||
break;
|
break;
|
||||||
case CSharpBuildStrategy.Auto:
|
case CSharpBuildStrategy.Auto:
|
||||||
var cleanTrapFolder =
|
var cleanTrapFolder =
|
||||||
BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_TRAP_DIR") ?? Actions.GetEnvironmentVariable("TRAP_FOLDER"));
|
BuildScript.DeleteDirectory(TrapDir);
|
||||||
var cleanSourceArchive =
|
var cleanSourceArchive =
|
||||||
BuildScript.DeleteDirectory(Actions.GetEnvironmentVariable("CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR") ?? Actions.GetEnvironmentVariable("SOURCE_ARCHIVE"));
|
BuildScript.DeleteDirectory(SourceArchiveDir);
|
||||||
var tryCleanExtractorArgsLogs =
|
var tryCleanExtractorArgsLogs =
|
||||||
BuildScript.Create(actions =>
|
BuildScript.Create(actions =>
|
||||||
{
|
{
|
||||||
@@ -376,38 +399,33 @@ namespace Semmle.Autobuild
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value of CODEQL_EXTRACTOR_CSHARP_ROOT environment variable.
|
/// Value of CODEQL_EXTRACTOR_CSHARP_ROOT environment variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string CodeQLExtractorCSharpRoot { get; private set; }
|
private string? CodeQLExtractorCSharpRoot { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Value of CODEQL_JAVA_HOME environment variable.
|
|
||||||
/// </summary>
|
|
||||||
public string CodeQLJavaHome { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value of SEMMLE_DIST environment variable.
|
/// Value of SEMMLE_DIST environment variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SemmleDist { get; private set; }
|
private string? SemmleDist { get; }
|
||||||
|
|
||||||
/// <summary>
|
public string Distribution { get; }
|
||||||
/// Value of SEMMLE_JAVA_HOME environment variable.
|
|
||||||
/// </summary>
|
public string JavaHome { get; }
|
||||||
public string SemmleJavaHome { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value of SEMMLE_PLATFORM_TOOLS environment variable.
|
/// Value of SEMMLE_PLATFORM_TOOLS environment variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SemmlePlatformTools { get; private set; }
|
public string? SemmlePlatformTools { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The absolute path of the odasa executable.
|
/// The absolute path of the odasa executable.
|
||||||
|
/// null if we are running in CodeQL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Odasa => SemmleDist == null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa");
|
public string? Odasa => SemmleDist is null ? null : Actions.PathCombine(SemmleDist, "tools", "odasa");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Construct a command that executed the given <paramref name="cmd"/> wrapped in
|
/// Construct a command that executed the given <paramref name="cmd"/> wrapped in
|
||||||
/// an <code>odasa --index</code>, unless indexing has been disabled, in which case
|
/// an <code>odasa --index</code>, unless indexing has been disabled, in which case
|
||||||
/// <paramref name="cmd"/> is run directly.
|
/// <paramref name="cmd"/> is run directly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="env">Additional environment variables.</param>
|
/// <param name="env">Additional environment variables.</param>
|
||||||
/// <param name="stdOut">The lines of stdout.</param>
|
/// <param name="stdOut">The lines of stdout.</param>
|
||||||
/// <returns>The process exit code.</returns>
|
/// <returns>The process exit code.</returns>
|
||||||
int RunProcess(string exe, string args, string workingDirectory, IDictionary<string, string> env, out IList<string> stdOut);
|
int RunProcess(string exe, string args, string? workingDirectory, IDictionary<string, string>? env, out IList<string> stdOut);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs a process but does not capture its output.
|
/// Runs a process but does not capture its output.
|
||||||
@@ -31,7 +31,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
||||||
/// <param name="env">Additional environment variables.</param>
|
/// <param name="env">Additional environment variables.</param>
|
||||||
/// <returns>The process exit code.</returns>
|
/// <returns>The process exit code.</returns>
|
||||||
int RunProcess(string exe, string args, string workingDirectory, IDictionary<string, string> env);
|
int RunProcess(string exe, string args, string? workingDirectory, IDictionary<string, string>? env);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tests whether a file exists, File.Exists().
|
/// Tests whether a file exists, File.Exists().
|
||||||
@@ -63,7 +63,7 @@ namespace Semmle.Autobuild
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name of the variable.</param>
|
/// <param name="name">The name of the variable.</param>
|
||||||
/// <returns>The string value, or null if the variable is not defined.</returns>
|
/// <returns>The string value, or null if the variable is not defined.</returns>
|
||||||
string GetEnvironmentVariable(string name);
|
string? GetEnvironmentVariable(string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the current directory, Directory.GetCurrentDirectory().
|
/// Gets the current directory, Directory.GetCurrentDirectory().
|
||||||
@@ -130,7 +130,7 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
bool IBuildActions.FileExists(string file) => File.Exists(file);
|
bool IBuildActions.FileExists(string file) => File.Exists(file);
|
||||||
|
|
||||||
ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workingDirectory, IDictionary<string, string> environment, bool redirectStandardOutput)
|
ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string? workingDirectory, IDictionary<string, string>? environment, bool redirectStandardOutput)
|
||||||
{
|
{
|
||||||
var pi = new ProcessStartInfo(exe, arguments)
|
var pi = new ProcessStartInfo(exe, arguments)
|
||||||
{
|
{
|
||||||
@@ -146,7 +146,7 @@ namespace Semmle.Autobuild
|
|||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary<string, string> environment)
|
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
|
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
|
||||||
using (var p = Process.Start(pi))
|
using (var p = Process.Start(pi))
|
||||||
@@ -156,7 +156,7 @@ namespace Semmle.Autobuild
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary<string, string> environment, out IList<string> stdOut)
|
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? environment, out IList<string> stdOut)
|
||||||
{
|
{
|
||||||
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true);
|
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true);
|
||||||
return pi.ReadOutput(out stdOut);
|
return pi.ReadOutput(out stdOut);
|
||||||
@@ -166,7 +166,7 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
bool IBuildActions.DirectoryExists(string dir) => Directory.Exists(dir);
|
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();
|
string IBuildActions.GetCurrentDirectory() => Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace Semmle.Autobuild
|
|||||||
chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}");
|
chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}");
|
||||||
var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script);
|
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
|
// A specific .NET Core version may be required
|
||||||
return chmodScript & DotNetRule.WithDotNet(builder, environment =>
|
return chmodScript & DotNetRule.WithDotNet(builder, environment =>
|
||||||
|
|||||||
@@ -48,8 +48,9 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
class BuildCommand : BuildScript
|
class BuildCommand : BuildScript
|
||||||
{
|
{
|
||||||
readonly string exe, arguments, workingDirectory;
|
readonly string exe, arguments;
|
||||||
readonly IDictionary<string, string> environment;
|
readonly string? workingDirectory;
|
||||||
|
readonly IDictionary<string, string>? environment;
|
||||||
readonly bool silent;
|
readonly bool silent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -60,7 +61,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="silent">Whether this command should run silently.</param>
|
/// <param name="silent">Whether this command should run silently.</param>
|
||||||
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
||||||
/// <param name="environment">Additional environment variables.</param>
|
/// <param name="environment">Additional environment variables.</param>
|
||||||
public BuildCommand(string exe, string argumentsOpt, bool silent, string workingDirectory = null, IDictionary<string, string> environment = null)
|
public BuildCommand(string exe, string argumentsOpt, bool silent, string? workingDirectory = null, IDictionary<string, string>? environment = null)
|
||||||
{
|
{
|
||||||
this.exe = exe;
|
this.exe = exe;
|
||||||
this.arguments = argumentsOpt ?? "";
|
this.arguments = argumentsOpt ?? "";
|
||||||
@@ -131,8 +132,8 @@ namespace Semmle.Autobuild
|
|||||||
class BindBuildScript : BuildScript
|
class BindBuildScript : BuildScript
|
||||||
{
|
{
|
||||||
readonly BuildScript s1;
|
readonly BuildScript s1;
|
||||||
readonly Func<IList<string>, int, BuildScript> s2a;
|
readonly Func<IList<string>, int, BuildScript>? s2a;
|
||||||
readonly Func<int, BuildScript> s2b;
|
readonly Func<int, BuildScript>? s2b;
|
||||||
public BindBuildScript(BuildScript s1, Func<IList<string>, int, BuildScript> s2)
|
public BindBuildScript(BuildScript s1, Func<IList<string>, int, BuildScript> s2)
|
||||||
{
|
{
|
||||||
this.s1 = s1;
|
this.s1 = s1;
|
||||||
@@ -154,14 +155,19 @@ namespace Semmle.Autobuild
|
|||||||
return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack);
|
return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret1 = s1.Run(actions, startCallback, exitCallBack);
|
if (s2b != null)
|
||||||
return s2b(ret1).Run(actions, startCallback, exitCallBack);
|
{
|
||||||
|
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<string, bool> startCallback, Action<int, string, bool> exitCallBack, out IList<string> stdout)
|
public override int Run(IBuildActions actions, Action<string, bool> startCallback, Action<int, string, bool> exitCallBack, out IList<string> stdout)
|
||||||
{
|
{
|
||||||
var ret1 = s1.Run(actions, startCallback, exitCallBack, out var stdout1);
|
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<string>();
|
var @out = new List<string>();
|
||||||
@out.AddRange(stdout1);
|
@out.AddRange(stdout1);
|
||||||
@out.AddRange(stdout2);
|
@out.AddRange(stdout2);
|
||||||
@@ -177,7 +183,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="silent">Whether the executable should run silently.</param>
|
/// <param name="silent">Whether the executable should run silently.</param>
|
||||||
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
||||||
/// <param name="environment">Additional environment variables.</param>
|
/// <param name="environment">Additional environment variables.</param>
|
||||||
public static BuildScript Create(string exe, string argumentsOpt, bool silent, string workingDirectory, IDictionary<string, string> environment) =>
|
public static BuildScript Create(string exe, string argumentsOpt, bool silent, string? workingDirectory, IDictionary<string, string>? environment) =>
|
||||||
new BuildCommand(exe, argumentsOpt, silent, workingDirectory, environment);
|
new BuildCommand(exe, argumentsOpt, silent, workingDirectory, environment);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ namespace Semmle.Autobuild
|
|||||||
|
|
||||||
readonly StringBuilder arguments;
|
readonly StringBuilder arguments;
|
||||||
bool firstCommand;
|
bool firstCommand;
|
||||||
string executable;
|
string? executable;
|
||||||
readonly EscapeMode escapingMode;
|
readonly EscapeMode escapingMode;
|
||||||
readonly string workingDirectory;
|
readonly string? workingDirectory;
|
||||||
readonly IDictionary<string, string> environment;
|
readonly IDictionary<string, string>? environment;
|
||||||
readonly bool silent;
|
readonly bool silent;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,7 +25,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
/// <param name="workingDirectory">The working directory (<code>null</code> for current directory).</param>
|
||||||
/// <param name="environment">Additional environment variables.</param>
|
/// <param name="environment">Additional environment variables.</param>
|
||||||
/// <param name="silent">Whether this command should be run silently.</param>
|
/// <param name="silent">Whether this command should be run silently.</param>
|
||||||
public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDictionary<string, string> environment = null, bool silent = false)
|
public CommandBuilder(IBuildActions actions, string? workingDirectory = null, IDictionary<string, string>? environment = null, bool silent = false)
|
||||||
{
|
{
|
||||||
arguments = new StringBuilder();
|
arguments = new StringBuilder();
|
||||||
if (actions.IsWindows())
|
if (actions.IsWindows())
|
||||||
@@ -50,7 +50,7 @@ namespace Semmle.Autobuild
|
|||||||
RunCommand(odasa, "index --auto");
|
RunCommand(odasa, "index --auto");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder CallBatFile(string batFile, string argumentsOpt = null)
|
public CommandBuilder CallBatFile(string batFile, string? argumentsOpt = null)
|
||||||
{
|
{
|
||||||
NextCommand();
|
NextCommand();
|
||||||
arguments.Append(" CALL");
|
arguments.Append(" CALL");
|
||||||
@@ -66,7 +66,7 @@ namespace Semmle.Autobuild
|
|||||||
/// <param name="command">The command to run.</param>
|
/// <param name="command">The command to run.</param>
|
||||||
/// <param name="argumentsOpt">Additional arguments.</param>
|
/// <param name="argumentsOpt">Additional arguments.</param>
|
||||||
/// <returns>this for chaining calls.</returns>
|
/// <returns>this for chaining calls.</returns>
|
||||||
public CommandBuilder IndexCommand(string odasa, string command, string argumentsOpt = null)
|
public CommandBuilder IndexCommand(string odasa, string command, string? argumentsOpt = null)
|
||||||
{
|
{
|
||||||
OdasaIndex(odasa);
|
OdasaIndex(odasa);
|
||||||
QuoteArgument(command);
|
QuoteArgument(command);
|
||||||
@@ -151,7 +151,7 @@ namespace Semmle.Autobuild
|
|||||||
arguments.Append(' ');
|
arguments.Append(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder Argument(string argumentsOpt)
|
public CommandBuilder Argument(string? argumentsOpt)
|
||||||
{
|
{
|
||||||
if (argumentsOpt != null)
|
if (argumentsOpt != null)
|
||||||
{
|
{
|
||||||
@@ -169,7 +169,7 @@ namespace Semmle.Autobuild
|
|||||||
arguments.Append(" &&");
|
arguments.Append(" &&");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandBuilder RunCommand(string exe, string argumentsOpt = null)
|
public CommandBuilder RunCommand(string exe, string? argumentsOpt = null)
|
||||||
{
|
{
|
||||||
var (exe0, arg0) =
|
var (exe0, arg0) =
|
||||||
escapingMode == EscapeMode.Process && exe.EndsWith(".exe", System.StringComparison.Ordinal)
|
escapingMode == EscapeMode.Process && exe.EndsWith(".exe", System.StringComparison.Ordinal)
|
||||||
@@ -193,6 +193,14 @@ namespace Semmle.Autobuild
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a build script that contains just this command.
|
/// Returns a build script that contains just this command.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,13 +56,13 @@ namespace Semmle.Autobuild
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static BuildScript WithDotNet(Autobuilder builder, Func<string, IDictionary<string, string>, bool, BuildScript> f)
|
static BuildScript WithDotNet(Autobuilder builder, Func<string?, IDictionary<string, string>?, 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);
|
var installScript = DownloadDotNet(builder, installDir);
|
||||||
return BuildScript.Bind(installScript, installed =>
|
return BuildScript.Bind(installScript, installed =>
|
||||||
{
|
{
|
||||||
Dictionary<string, string> env;
|
Dictionary<string, string>? env;
|
||||||
if (installed == 0)
|
if (installed == 0)
|
||||||
{
|
{
|
||||||
// The installation succeeded, so use the newly installed .NET Core
|
// The installation succeeded, so use the newly installed .NET Core
|
||||||
@@ -120,7 +120,7 @@ namespace Semmle.Autobuild
|
|||||||
/// variables needed by the installed .NET Core (<code>null</code> when no variables
|
/// variables needed by the installed .NET Core (<code>null</code> when no variables
|
||||||
/// are needed).
|
/// are needed).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static BuildScript WithDotNet(Autobuilder builder, Func<IDictionary<string, string>, BuildScript> f)
|
public static BuildScript WithDotNet(Autobuilder builder, Func<IDictionary<string, string>?, BuildScript> f)
|
||||||
=> WithDotNet(builder, (_1, env, _2) => f(env));
|
=> WithDotNet(builder, (_1, env, _2) => f(env));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -265,10 +265,10 @@ Invoke-Command -ScriptBlock $ScriptBlock";
|
|||||||
return listSdks.Script;
|
return listSdks.Script;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string DotNetCommand(IBuildActions actions, string dotNetPath) =>
|
static string DotNetCommand(IBuildActions actions, string? dotNetPath) =>
|
||||||
dotNetPath != null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
dotNetPath != null ? actions.PathCombine(dotNetPath, "dotnet") : "dotnet";
|
||||||
|
|
||||||
BuildScript GetInfoCommand(IBuildActions actions, string dotNetPath, IDictionary<string, string> environment)
|
BuildScript GetInfoCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
var info = new CommandBuilder(actions, null, environment).
|
var info = new CommandBuilder(actions, null, environment).
|
||||||
RunCommand(DotNetCommand(actions, dotNetPath)).
|
RunCommand(DotNetCommand(actions, dotNetPath)).
|
||||||
@@ -276,7 +276,7 @@ Invoke-Command -ScriptBlock $ScriptBlock";
|
|||||||
return info.Script;
|
return info.Script;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBuilder GetCleanCommand(IBuildActions actions, string dotNetPath, IDictionary<string, string> environment)
|
CommandBuilder GetCleanCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
var clean = new CommandBuilder(actions, null, environment).
|
var clean = new CommandBuilder(actions, null, environment).
|
||||||
RunCommand(DotNetCommand(actions, dotNetPath)).
|
RunCommand(DotNetCommand(actions, dotNetPath)).
|
||||||
@@ -284,7 +284,7 @@ Invoke-Command -ScriptBlock $ScriptBlock";
|
|||||||
return clean;
|
return clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBuilder GetRestoreCommand(IBuildActions actions, string dotNetPath, IDictionary<string, string> environment)
|
CommandBuilder GetRestoreCommand(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
var restore = new CommandBuilder(actions, null, environment).
|
var restore = new CommandBuilder(actions, null, environment).
|
||||||
RunCommand(DotNetCommand(actions, dotNetPath)).
|
RunCommand(DotNetCommand(actions, dotNetPath)).
|
||||||
@@ -292,7 +292,7 @@ Invoke-Command -ScriptBlock $ScriptBlock";
|
|||||||
return restore;
|
return restore;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string dotNetPath, IDictionary<string, string> environment)
|
static BuildScript GetInstalledRuntimesScript(IBuildActions actions, string? dotNetPath, IDictionary<string, string>? environment)
|
||||||
{
|
{
|
||||||
var listSdks = new CommandBuilder(actions, environment: environment, silent: true).
|
var listSdks = new CommandBuilder(actions, environment: environment, silent: true).
|
||||||
RunCommand(DotNetCommand(actions, dotNetPath)).
|
RunCommand(DotNetCommand(actions, dotNetPath)).
|
||||||
@@ -309,7 +309,7 @@ Invoke-Command -ScriptBlock $ScriptBlock";
|
|||||||
/// hence the need for CLR tracing), by adding a
|
/// hence the need for CLR tracing), by adding a
|
||||||
/// `/p:UseSharedCompilation=false` argument.
|
/// `/p:UseSharedCompilation=false` argument.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
BuildScript GetBuildScript(Autobuilder builder, string dotNetPath, IDictionary<string, string> environment, bool compatibleClr, string projOrSln)
|
BuildScript GetBuildScript(Autobuilder builder, string? dotNetPath, IDictionary<string, string>? environment, bool compatibleClr, string projOrSln)
|
||||||
{
|
{
|
||||||
var build = new CommandBuilder(builder.Actions, null, environment);
|
var build = new CommandBuilder(builder.Actions, null, environment);
|
||||||
var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, dotNetPath)).
|
var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, dotNetPath)).
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ namespace Semmle.Autobuild
|
|||||||
string target = builder.Options.MsBuildTarget != null
|
string target = builder.Options.MsBuildTarget != null
|
||||||
? builder.Options.MsBuildTarget
|
? builder.Options.MsBuildTarget
|
||||||
: "rebuild";
|
: "rebuild";
|
||||||
string platform = builder.Options.MsBuildPlatform != null
|
string? platform = builder.Options.MsBuildPlatform != null
|
||||||
? builder.Options.MsBuildPlatform
|
? builder.Options.MsBuildPlatform
|
||||||
: projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null;
|
: projectOrSolution is ISolution s1 ? s1.DefaultPlatformName : null;
|
||||||
string configuration = builder.Options.MsBuildConfiguration != null
|
string? configuration = builder.Options.MsBuildConfiguration != null
|
||||||
? builder.Options.MsBuildConfiguration
|
? builder.Options.MsBuildConfiguration
|
||||||
: projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null;
|
: projectOrSolution is ISolution s2 ? s2.DefaultConfigurationName : null;
|
||||||
|
|
||||||
@@ -96,9 +96,9 @@ namespace Semmle.Autobuild
|
|||||||
///
|
///
|
||||||
/// Returns <code>null</code> when no version is specified.
|
/// Returns <code>null</code> when no version is specified.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static VcVarsBatFile GetVcVarsBatFile(Autobuilder builder)
|
public static VcVarsBatFile? GetVcVarsBatFile(Autobuilder builder)
|
||||||
{
|
{
|
||||||
VcVarsBatFile vsTools = null;
|
VcVarsBatFile? vsTools = null;
|
||||||
|
|
||||||
if (builder.Options.VsToolsVersion != null)
|
if (builder.Options.VsToolsVersion != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,23 +6,27 @@ namespace Semmle.Autobuild
|
|||||||
{
|
{
|
||||||
static int Main()
|
static int Main()
|
||||||
{
|
{
|
||||||
var options = new AutobuildOptions();
|
|
||||||
var actions = SystemBuildActions.Instance;
|
|
||||||
|
|
||||||
try
|
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)
|
catch (ArgumentOutOfRangeException ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine("The value \"{0}\" for parameter \"{1}\" is invalid", ex.ActualValue, ex.ParamName);
|
Console.WriteLine("The value \"{0}\" for parameter \"{1}\" is invalid", ex.ActualValue, ex.ParamName);
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
var builder = new Autobuilder(actions, options);
|
|
||||||
|
|
||||||
Console.WriteLine($"Semmle autobuilder for {options.Language}");
|
|
||||||
|
|
||||||
return builder.AttemptBuild();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace Semmle.Autobuild
|
|||||||
foreach (var include in projectFileIncludes.Concat(projectFilesIncludes))
|
foreach (var include in projectFileIncludes.Concat(projectFilesIncludes))
|
||||||
{
|
{
|
||||||
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
|
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;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Semmle.Autobuild
|
namespace Semmle.Autobuild
|
||||||
@@ -24,6 +25,8 @@ namespace Semmle.Autobuild
|
|||||||
{
|
{
|
||||||
public string FullPath { get; private set; }
|
public string FullPath { get; private set; }
|
||||||
|
|
||||||
|
public string DirectoryName => Path.GetDirectoryName(FullPath) ?? "";
|
||||||
|
|
||||||
protected ProjectOrSolution(Autobuilder builder, string path)
|
protected ProjectOrSolution(Autobuilder builder, string path)
|
||||||
{
|
{
|
||||||
FullPath = builder.Actions.GetFullPath(path);
|
FullPath = builder.Actions.GetFullPath(path);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<StartupObject />
|
<StartupObject />
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Semmle.Autobuild
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class Solution : ProjectOrSolution, ISolution
|
class Solution : ProjectOrSolution, ISolution
|
||||||
{
|
{
|
||||||
readonly SolutionFile solution;
|
readonly SolutionFile? solution;
|
||||||
|
|
||||||
readonly IEnumerable<Project> includedProjects;
|
readonly IEnumerable<Project> includedProjects;
|
||||||
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects;
|
public override IEnumerable<IProjectOrSolution> IncludedProjects => includedProjects;
|
||||||
@@ -81,7 +81,7 @@ namespace Semmle.Autobuild
|
|||||||
includedProjects =
|
includedProjects =
|
||||||
solution.ProjectsInOrder.
|
solution.ProjectsInOrder.
|
||||||
Where(p => p.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat).
|
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)).
|
Select(p => new Project(builder, p)).
|
||||||
ToArray();
|
ToArray();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.IO;
|
namespace Semmle.Autobuild
|
||||||
|
|
||||||
namespace Semmle.Autobuild
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Build using standalone extraction.
|
/// Build using standalone extraction.
|
||||||
@@ -9,8 +7,11 @@ namespace Semmle.Autobuild
|
|||||||
{
|
{
|
||||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
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 standalone = builder.Actions.PathCombine(builder.SemmlePlatformTools, "csharp", "Semmle.Extraction.CSharp.Standalone");
|
||||||
var cmd = new CommandBuilder(builder.Actions);
|
var cmd = new CommandBuilder(builder.Actions);
|
||||||
cmd.RunCommand(standalone);
|
cmd.RunCommand(standalone);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
{
|
{
|
||||||
public BuildScript Analyse(Autobuilder builder, bool auto)
|
public BuildScript Analyse(Autobuilder builder, bool auto)
|
||||||
{
|
{
|
||||||
if (!builder.Options.Indexing)
|
if (!builder.Options.Indexing || builder.Odasa is null)
|
||||||
return BuildScript.Success;
|
return BuildScript.Success;
|
||||||
|
|
||||||
var command = new CommandBuilder(builder.Actions).
|
var command = new CommandBuilder(builder.Actions).
|
||||||
|
|||||||
@@ -163,7 +163,19 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filepath">The filename to query.</param>
|
/// <param name="filepath">The filename to query.</param>
|
||||||
/// <returns>The assembly info.</returns>
|
/// <returns>The assembly info.</returns>
|
||||||
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.
|
// List of pending DLLs to index.
|
||||||
readonly List<string> dlls = new List<string>();
|
readonly List<string> dlls = new List<string>();
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
using System;
|
using Semmle.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using Semmle.Util;
|
|
||||||
using Semmle.Extraction.CSharp.Standalone;
|
using Semmle.Extraction.CSharp.Standalone;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Semmle.BuildAnalyser
|
namespace Semmle.BuildAnalyser
|
||||||
{
|
{
|
||||||
@@ -43,19 +46,18 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Main implementation of the build analysis.
|
/// Main implementation of the build analysis.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class BuildAnalysis : IBuildAnalysis
|
class BuildAnalysis : IBuildAnalysis, IDisposable
|
||||||
{
|
{
|
||||||
readonly AssemblyCache assemblyCache;
|
private readonly AssemblyCache assemblyCache;
|
||||||
readonly NugetPackages nuget;
|
private readonly NugetPackages nuget;
|
||||||
readonly IProgressMonitor progressMonitor;
|
private readonly IProgressMonitor progressMonitor;
|
||||||
HashSet<string> usedReferences = new HashSet<string>();
|
private readonly IDictionary<string, bool> usedReferences = new ConcurrentDictionary<string, bool>();
|
||||||
readonly HashSet<string> usedSources = new HashSet<string>();
|
private readonly IDictionary<string, bool> sources = new ConcurrentDictionary<string, bool>();
|
||||||
readonly HashSet<string> missingSources = new HashSet<string>();
|
private readonly IDictionary<string, string> unresolvedReferences = new ConcurrentDictionary<string, string>();
|
||||||
readonly Dictionary<string, string> unresolvedReferences = new Dictionary<string, string>();
|
private readonly DirectoryInfo sourceDir;
|
||||||
readonly DirectoryInfo sourceDir;
|
private int failedProjects, succeededProjects;
|
||||||
int failedProjects, succeededProjects;
|
private readonly string[] allSources;
|
||||||
readonly string[] allSources;
|
private int conflictedReferences = 0;
|
||||||
int conflictedReferences = 0;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a C# build analysis.
|
/// Performs a C# build analysis.
|
||||||
@@ -64,6 +66,8 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// <param name="progress">Display of analysis progress.</param>
|
/// <param name="progress">Display of analysis progress.</param>
|
||||||
public BuildAnalysis(Options options, IProgressMonitor progress)
|
public BuildAnalysis(Options options, IProgressMonitor progress)
|
||||||
{
|
{
|
||||||
|
var startTime = DateTime.Now;
|
||||||
|
|
||||||
progressMonitor = progress;
|
progressMonitor = progress;
|
||||||
sourceDir = new DirectoryInfo(options.SrcDir);
|
sourceDir = new DirectoryInfo(options.SrcDir);
|
||||||
|
|
||||||
@@ -74,36 +78,43 @@ namespace Semmle.BuildAnalyser
|
|||||||
Where(d => !options.ExcludesFile(d)).
|
Where(d => !options.ExcludesFile(d)).
|
||||||
ToArray();
|
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)
|
if (options.UseNuGet)
|
||||||
{
|
{
|
||||||
nuget = new NugetPackages(sourceDir.FullName);
|
try
|
||||||
ReadNugetFiles();
|
{
|
||||||
dllDirNames = dllDirNames.Concat(Enumerators.Singleton(nuget.PackageDirectory));
|
nuget = new NugetPackages(sourceDir.FullName, PackageDirectory);
|
||||||
|
ReadNugetFiles();
|
||||||
|
}
|
||||||
|
catch(FileNotFoundException)
|
||||||
|
{
|
||||||
|
progressMonitor.MissingNuGet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find DLLs in the .Net Framework
|
// Find DLLs in the .Net Framework
|
||||||
if (options.ScanNetFrameworkDlls)
|
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.
|
RestoreSolutions(solutions);
|
||||||
if (options.SolutionFile != null)
|
dllDirNames.Add(PackageDirectory.DirInfo.FullName);
|
||||||
{
|
assemblyCache = new BuildAnalyser.AssemblyCache(dllDirNames, progress);
|
||||||
AnalyseSolution(options.SolutionFile);
|
AnalyseSolutions(solutions);
|
||||||
}
|
|
||||||
else if (options.AnalyseCsProjFiles)
|
|
||||||
{
|
|
||||||
AnalyseProjectFiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options.AnalyseCsProjFiles)
|
foreach (var filename in assemblyCache.AllAssemblies.Select(a => a.Filename))
|
||||||
{
|
UseReference(filename);
|
||||||
usedReferences = new HashSet<string>(assemblyCache.AllAssemblies.Select(a => a.Filename));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResolveConflicts();
|
ResolveConflicts();
|
||||||
@@ -114,7 +125,7 @@ namespace Semmle.BuildAnalyser
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Output the findings
|
// Output the findings
|
||||||
foreach (var r in usedReferences)
|
foreach (var r in usedReferences.Keys)
|
||||||
{
|
{
|
||||||
progressMonitor.ResolvedReference(r);
|
progressMonitor.ResolvedReference(r);
|
||||||
}
|
}
|
||||||
@@ -132,7 +143,27 @@ namespace Semmle.BuildAnalyser
|
|||||||
UnresolvedReferences.Count(),
|
UnresolvedReferences.Count(),
|
||||||
conflictedReferences,
|
conflictedReferences,
|
||||||
succeededProjects + failedProjects,
|
succeededProjects + failedProjects,
|
||||||
failedProjects);
|
failedProjects,
|
||||||
|
DateTime.Now - startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes a unique temp directory for the packages associated
|
||||||
|
/// with this source tree. Use a SHA1 of the directory name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="srcDir"></param>
|
||||||
|
/// <returns>The full path of the temp directory.</returns>
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -143,7 +174,7 @@ namespace Semmle.BuildAnalyser
|
|||||||
void ResolveConflicts()
|
void ResolveConflicts()
|
||||||
{
|
{
|
||||||
var sortedReferences = usedReferences.
|
var sortedReferences = usedReferences.
|
||||||
Select(r => assemblyCache.GetAssemblyInfo(r)).
|
Select(r => assemblyCache.GetAssemblyInfo(r.Key)).
|
||||||
OrderBy(r => r.Version).
|
OrderBy(r => r.Version).
|
||||||
ToArray();
|
ToArray();
|
||||||
|
|
||||||
@@ -154,7 +185,9 @@ namespace Semmle.BuildAnalyser
|
|||||||
finalAssemblyList[r.Name] = r;
|
finalAssemblyList[r.Name] = r;
|
||||||
|
|
||||||
// Update the used references list
|
// Update the used references list
|
||||||
usedReferences = new HashSet<string>(finalAssemblyList.Select(r => r.Value.Filename));
|
usedReferences.Clear();
|
||||||
|
foreach (var r in finalAssemblyList.Select(r => r.Value.Filename))
|
||||||
|
UseReference(r);
|
||||||
|
|
||||||
// Report the results
|
// Report the results
|
||||||
foreach (var r in sortedReferences)
|
foreach (var r in sortedReferences)
|
||||||
@@ -183,7 +216,7 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// <param name="reference">The filename of the reference.</param>
|
/// <param name="reference">The filename of the reference.</param>
|
||||||
void UseReference(string reference)
|
void UseReference(string reference)
|
||||||
{
|
{
|
||||||
usedReferences.Add(reference);
|
usedReferences[reference] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -192,25 +225,18 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// <param name="sourceFile">The source file.</param>
|
/// <param name="sourceFile">The source file.</param>
|
||||||
void UseSource(FileInfo sourceFile)
|
void UseSource(FileInfo sourceFile)
|
||||||
{
|
{
|
||||||
if (sourceFile.Exists)
|
sources[sourceFile.FullName] = sourceFile.Exists;
|
||||||
{
|
|
||||||
usedSources.Add(sourceFile.FullName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
missingSources.Add(sourceFile.FullName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of resolved reference files.
|
/// The list of resolved reference files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> ReferenceFiles => this.usedReferences;
|
public IEnumerable<string> ReferenceFiles => this.usedReferences.Keys;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of source files used in projects.
|
/// The list of source files used in projects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> ProjectSourceFiles => usedSources;
|
public IEnumerable<string> ProjectSourceFiles => sources.Where(s => s.Value).Select(s => s.Key);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// All of the source files in the source directory.
|
/// 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
|
/// List of source files which were mentioned in project files but
|
||||||
/// do not exist on the file system.
|
/// do not exist on the file system.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<string> MissingSourceFiles => missingSources;
|
public IEnumerable<string> MissingSourceFiles => sources.Where(s => !s.Value).Select(s => s.Key);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Record that a particular reference couldn't be resolved.
|
/// Record that a particular reference couldn't be resolved.
|
||||||
@@ -239,74 +265,101 @@ namespace Semmle.BuildAnalyser
|
|||||||
unresolvedReferences[id] = projectFile;
|
unresolvedReferences[id] = projectFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
readonly TemporaryDirectory PackageDirectory;
|
||||||
/// Performs an analysis of all .csproj files.
|
|
||||||
/// </summary>
|
|
||||||
void AnalyseProjectFiles()
|
|
||||||
{
|
|
||||||
AnalyseProjectFiles(sourceDir.GetFiles("*.csproj", SearchOption.AllDirectories));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads all the source files and references from the given list of projects.
|
/// Reads all the source files and references from the given list of projects.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="projectFiles">The list of projects to analyse.</param>
|
/// <param name="projectFiles">The list of projects to analyse.</param>
|
||||||
void AnalyseProjectFiles(FileInfo[] projectFiles)
|
void AnalyseProjectFiles(IEnumerable<FileInfo> projectFiles)
|
||||||
{
|
{
|
||||||
progressMonitor.AnalysingProjectFiles(projectFiles.Count());
|
|
||||||
|
|
||||||
foreach (var proj in projectFiles)
|
foreach (var proj in projectFiles)
|
||||||
|
AnalyseProject(proj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalyseProject(FileInfo project)
|
||||||
|
{
|
||||||
|
if(!project.Exists)
|
||||||
{
|
{
|
||||||
try
|
progressMonitor.MissingProject(project.FullName);
|
||||||
{
|
return;
|
||||||
var csProj = new CsProjFile(proj);
|
}
|
||||||
|
|
||||||
foreach (var @ref in csProj.References)
|
try
|
||||||
{
|
{
|
||||||
AssemblyInfo resolved = assemblyCache.ResolveReference(@ref);
|
var csProj = new CsProjFile(project);
|
||||||
if (!resolved.Valid)
|
|
||||||
{
|
|
||||||
UnresolvedReference(@ref, proj.FullName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UseReference(resolved.Filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var src in csProj.Sources)
|
foreach (var @ref in csProj.References)
|
||||||
{
|
|
||||||
// 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;
|
AssemblyInfo resolved = assemblyCache.ResolveReference(@ref);
|
||||||
progressMonitor.FailedProjectFile(proj.FullName, ex.Message);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void RestoreSolutions(IEnumerable<string> solutions)
|
||||||
/// Delete packages directory.
|
|
||||||
/// </summary>
|
|
||||||
public void Cleanup()
|
|
||||||
{
|
{
|
||||||
if (nuget != null) nuget.Cleanup(progressMonitor);
|
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 }, Restore);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void AnalyseSolutions(IEnumerable<string> solutions)
|
||||||
/// Analyse all project files in a given solution only.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="solutionFile">The filename of the solution.</param>
|
|
||||||
public void AnalyseSolution(string solutionFile)
|
|
||||||
{
|
{
|
||||||
var sln = new SolutionFile(solutionFile);
|
Parallel.ForEach(solutions, new ParallelOptions { MaxDegreeOfParallelism = 4 } , solutionFile =>
|
||||||
AnalyseProjectFiles(sln.Projects.Select(p => new FileInfo(p)).ToArray());
|
{
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,18 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class CsProjFile
|
class CsProjFile
|
||||||
{
|
{
|
||||||
|
private string Filename { get; }
|
||||||
|
|
||||||
|
private string Directory => Path.GetDirectoryName(Filename);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the .csproj file.
|
/// Reads the .csproj file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The .csproj file.</param>
|
/// <param name="filename">The .csproj file.</param>
|
||||||
public CsProjFile(FileInfo filename)
|
public CsProjFile(FileInfo filename)
|
||||||
{
|
{
|
||||||
|
Filename = filename.FullName;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// This can fail if the .csproj is invalid or has
|
// 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.
|
/// and there seems to be no way to make it succeed. Fails on Linux.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The file to read.</param>
|
/// <param name="filename">The file to read.</param>
|
||||||
public void ReadMsBuildProject(FileInfo filename)
|
private void ReadMsBuildProject(FileInfo filename)
|
||||||
{
|
{
|
||||||
var msbuildProject = new Microsoft.Build.Execution.ProjectInstance(filename.FullName);
|
var msbuildProject = new Microsoft.Build.Execution.ProjectInstance(filename.FullName);
|
||||||
|
|
||||||
@@ -62,7 +68,7 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// fallback if ReadMsBuildProject() fails.
|
/// fallback if ReadMsBuildProject() fails.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The .csproj file.</param>
|
/// <param name="filename">The .csproj file.</param>
|
||||||
public void ReadProjectFileAsXml(FileInfo filename)
|
private void ReadProjectFileAsXml(FileInfo filename)
|
||||||
{
|
{
|
||||||
var projFile = new XmlDocument();
|
var projFile = new XmlDocument();
|
||||||
var mgr = new XmlNamespaceManager(projFile.NameTable);
|
var mgr = new XmlNamespaceManager(projFile.NameTable);
|
||||||
@@ -71,22 +77,48 @@ namespace Semmle.BuildAnalyser
|
|||||||
var projDir = filename.Directory;
|
var projDir = filename.Directory;
|
||||||
var root = projFile.DocumentElement;
|
var root = projFile.DocumentElement;
|
||||||
|
|
||||||
references =
|
// Figure out if it's dotnet core
|
||||||
root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Reference/@Include", mgr).
|
|
||||||
NodeList().
|
|
||||||
Select(node => node.Value).
|
|
||||||
ToArray();
|
|
||||||
|
|
||||||
var relativeCsIncludes =
|
bool netCoreProjectFile = root.GetAttribute("Sdk") == "Microsoft.NET.Sdk";
|
||||||
root.SelectNodes("/msbuild:Project/msbuild:ItemGroup/msbuild:Compile/@Include", mgr).
|
|
||||||
NodeList().
|
|
||||||
Select(node => node.Value).
|
|
||||||
ToArray();
|
|
||||||
|
|
||||||
csFiles = relativeCsIncludes.
|
if (netCoreProjectFile)
|
||||||
Select(cs => Path.DirectorySeparatorChar == '/' ? cs.Replace("\\", "/") : cs).
|
{
|
||||||
Select(f => Path.GetFullPath(Path.Combine(projDir.FullName, f))).
|
var relativeCsIncludes =
|
||||||
ToArray();
|
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;
|
string[] references;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Semmle.BuildAnalyser
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utilities to run the "dotnet" command.
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using System;
|
using Semmle.Util;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Semmle.BuildAnalyser
|
namespace Semmle.BuildAnalyser
|
||||||
{
|
{
|
||||||
@@ -19,10 +18,10 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// Create the package manager for a specified source tree.
|
/// Create the package manager for a specified source tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sourceDir">The source directory.</param>
|
/// <param name="sourceDir">The source directory.</param>
|
||||||
public NugetPackages(string sourceDir)
|
public NugetPackages(string sourceDir, TemporaryDirectory packageDirectory)
|
||||||
{
|
{
|
||||||
SourceDirectory = sourceDir;
|
SourceDirectory = sourceDir;
|
||||||
PackageDirectory = computeTempDirectory(sourceDir);
|
PackageDirectory = packageDirectory;
|
||||||
|
|
||||||
// Expect nuget.exe to be in a `nuget` directory under the directory containing this exe.
|
// Expect nuget.exe to be in a `nuget` directory under the directory containing this exe.
|
||||||
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||||
@@ -50,45 +49,12 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IEnumerable<FileInfo> PackageFiles => packages;
|
public IEnumerable<FileInfo> 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Download the packages to the temp folder.
|
/// Download the packages to the temp folder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pm">The progress monitor used for reporting errors etc.</param>
|
/// <param name="pm">The progress monitor used for reporting errors etc.</param>
|
||||||
public void InstallPackages(IProgressMonitor pm)
|
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)
|
foreach (var package in packages)
|
||||||
{
|
{
|
||||||
RestoreNugetPackage(package.FullName, pm);
|
RestoreNugetPackage(package.FullName, pm);
|
||||||
@@ -109,31 +75,7 @@ namespace Semmle.BuildAnalyser
|
|||||||
/// This will be in the Temp location
|
/// This will be in the Temp location
|
||||||
/// so as to not trample the source tree.
|
/// so as to not trample the source tree.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string PackageDirectory
|
public TemporaryDirectory PackageDirectory { get; }
|
||||||
{
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Computes a unique temp directory for the packages associated
|
|
||||||
/// with this source tree. Use a SHA1 of the directory name.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="srcDir"></param>
|
|
||||||
/// <returns>The full path of the temp directory.</returns>
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restore all files in a specified package.
|
/// Restore all files in a specified package.
|
||||||
@@ -171,16 +113,15 @@ namespace Semmle.BuildAnalyser
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var p = Process.Start(pi))
|
using var p = Process.Start(pi);
|
||||||
{
|
|
||||||
string output = p.StandardOutput.ReadToEnd();
|
|
||||||
string error = p.StandardError.ReadToEnd();
|
|
||||||
|
|
||||||
p.WaitForExit();
|
string output = p.StandardOutput.ReadToEnd();
|
||||||
if (p.ExitCode != 0)
|
string error = p.StandardError.ReadToEnd();
|
||||||
{
|
|
||||||
pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
|
p.WaitForExit();
|
||||||
}
|
if (p.ExitCode != 0)
|
||||||
|
{
|
||||||
|
pm.FailedNugetCommand(pi.FileName, pi.Arguments, output + error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Searches for source/references and creates separate extractions.
|
/// Searches for source/references and creates separate extractions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class Analysis
|
class Analysis : IDisposable
|
||||||
{
|
{
|
||||||
readonly ILogger logger;
|
readonly ILogger logger;
|
||||||
|
|
||||||
@@ -71,12 +71,9 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
projectExtraction.Sources.AddRange(options.SolutionFile == null ? buildAnalysis.AllSourceFiles : buildAnalysis.ProjectSourceFiles);
|
projectExtraction.Sources.AddRange(options.SolutionFile == null ? buildAnalysis.AllSourceFiles : buildAnalysis.ProjectSourceFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void Dispose()
|
||||||
/// Delete any Nuget assemblies.
|
|
||||||
/// </summary>
|
|
||||||
public void Cleanup()
|
|
||||||
{
|
{
|
||||||
buildAnalysis.Cleanup();
|
buildAnalysis.Dispose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -85,8 +82,9 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
static int Main(string[] args)
|
static int Main(string[] args)
|
||||||
{
|
{
|
||||||
var options = Options.Create(args);
|
var options = Options.Create(args);
|
||||||
|
// options.CIL = true; // To do: Enable this
|
||||||
var output = new ConsoleLogger(options.Verbosity);
|
var output = new ConsoleLogger(options.Verbosity);
|
||||||
var a = new Analysis(output);
|
using var a = new Analysis(output);
|
||||||
|
|
||||||
if (options.Help)
|
if (options.Help)
|
||||||
{
|
{
|
||||||
@@ -97,6 +95,8 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
if (options.Errors)
|
if (options.Errors)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
var start = DateTime.Now;
|
||||||
|
|
||||||
output.Log(Severity.Info, "Running C# standalone extractor");
|
output.Log(Severity.Info, "Running C# standalone extractor");
|
||||||
a.AnalyseProjects(options);
|
a.AnalyseProjects(options);
|
||||||
int sourceFiles = a.Extraction.Sources.Count();
|
int sourceFiles = a.Extraction.Sources.Count();
|
||||||
@@ -117,10 +117,9 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
new ExtractionProgress(output),
|
new ExtractionProgress(output),
|
||||||
new FileLogger(options.Verbosity, Extractor.GetCSharpLogPath()),
|
new FileLogger(options.Verbosity, Extractor.GetCSharpLogPath()),
|
||||||
options);
|
options);
|
||||||
output.Log(Severity.Info, "Extraction complete");
|
output.Log(Severity.Info, $"Extraction completed in {DateTime.Now-start}");
|
||||||
}
|
}
|
||||||
|
|
||||||
a.Cleanup();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +150,7 @@ namespace Semmle.Extraction.CSharp.Standalone
|
|||||||
|
|
||||||
public void MissingSummary(int missingTypes, int missingNamespaces)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Semmle.Util.Logging;
|
using Semmle.Util.Logging;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Semmle.BuildAnalyser
|
namespace Semmle.BuildAnalyser
|
||||||
{
|
{
|
||||||
@@ -9,15 +10,17 @@ namespace Semmle.BuildAnalyser
|
|||||||
{
|
{
|
||||||
void FindingFiles(string dir);
|
void FindingFiles(string dir);
|
||||||
void UnresolvedReference(string id, string project);
|
void UnresolvedReference(string id, string project);
|
||||||
void AnalysingProjectFiles(int count);
|
void AnalysingSolution(string filename);
|
||||||
void FailedProjectFile(string filename, string reason);
|
void FailedProjectFile(string filename, string reason);
|
||||||
void FailedNugetCommand(string exe, string args, string message);
|
void FailedNugetCommand(string exe, string args, string message);
|
||||||
void NugetInstall(string package);
|
void NugetInstall(string package);
|
||||||
void ResolvedReference(string filename);
|
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 Warning(string message);
|
||||||
void ResolvedConflict(string asm1, string asm2);
|
void ResolvedConflict(string asm1, string asm2);
|
||||||
void MissingProject(string projectFile);
|
void MissingProject(string projectFile);
|
||||||
|
void CommandFailed(string exe, string arguments, int exitCode);
|
||||||
|
void MissingNuGet();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProgressMonitor : IProgressMonitor
|
class ProgressMonitor : IProgressMonitor
|
||||||
@@ -46,9 +49,9 @@ namespace Semmle.BuildAnalyser
|
|||||||
logger.Log(Severity.Debug, "Unresolved {0} referenced by {1}", id, project);
|
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)
|
public void FailedProjectFile(string filename, string reason)
|
||||||
@@ -73,7 +76,9 @@ namespace Semmle.BuildAnalyser
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void Summary(int existingSources, int usedSources, int missingSources,
|
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, "");
|
||||||
logger.Log(Severity.Info, "Build analysis summary:");
|
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} resolved assembly conflicts", resolvedConflicts);
|
||||||
logger.Log(Severity.Info, "{0, 6} projects", totalProjects);
|
logger.Log(Severity.Info, "{0, 6} projects", totalProjects);
|
||||||
logger.Log(Severity.Info, "{0, 6} missing/failed projects", failedProjects);
|
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)
|
public void Warning(string message)
|
||||||
@@ -94,12 +100,22 @@ namespace Semmle.BuildAnalyser
|
|||||||
|
|
||||||
public void ResolvedConflict(string asm1, string asm2)
|
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)
|
public void MissingProject(string projectFile)
|
||||||
{
|
{
|
||||||
logger.Log(Severity.Info, "Solution is missing {0}", 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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
||||||
|
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ namespace Semmle.BuildAnalyser
|
|||||||
{
|
{
|
||||||
readonly Microsoft.Build.Construction.SolutionFile solutionFile;
|
readonly Microsoft.Build.Construction.SolutionFile solutionFile;
|
||||||
|
|
||||||
|
private string FullPath { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read the file.
|
/// Read the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -19,8 +21,8 @@ namespace Semmle.BuildAnalyser
|
|||||||
public SolutionFile(string filename)
|
public SolutionFile(string filename)
|
||||||
{
|
{
|
||||||
// SolutionFile.Parse() expects a rooted path.
|
// SolutionFile.Parse() expects a rooted path.
|
||||||
var fullPath = Path.GetFullPath(filename);
|
FullPath = Path.GetFullPath(filename);
|
||||||
solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(fullPath);
|
solutionFile = Microsoft.Build.Construction.SolutionFile.Parse(FullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEntity target)
|
Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEntity target)
|
||||||
: base(info.SetKind(AccessKind(info.Context, symbol)))
|
: 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)
|
if (implicitThis && !symbol.IsStatic)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||||||
if (symbol == null)
|
if (symbol == null)
|
||||||
{
|
{
|
||||||
info.Context.ModelError(info.Node, "Failed to determine symbol for member access");
|
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;
|
ExprKind kind;
|
||||||
|
|||||||
@@ -23,7 +23,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
|
|
||||||
protected override void Populate(TextWriter trapFile)
|
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_declarations(this, ns);
|
||||||
trapFile.namespace_declaration_location(this, cx.Create(Node.Name.GetLocation()));
|
trapFile.namespace_declaration_location(this, cx.Create(Node.Name.GetLocation()));
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
{
|
{
|
||||||
if (symbol.TypeKind == TypeKind.Error)
|
if (symbol.TypeKind == TypeKind.Error)
|
||||||
{
|
{
|
||||||
Context.Extractor.MissingType(symbol.ToString());
|
Context.Extractor.MissingType(symbol.ToString(), Context.FromSource);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||||||
|
|
||||||
if (namespaceSymbol == null)
|
if (namespaceSymbol == null)
|
||||||
{
|
{
|
||||||
cx.Extractor.MissingNamespace(Node.Name.ToFullString());
|
cx.Extractor.MissingNamespace(Node.Name.ToFullString(), cx.FromSource);
|
||||||
cx.ModelError(Node, "Namespace not found");
|
cx.ModelError(Node, "Namespace not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -214,7 +214,6 @@ namespace Semmle.Extraction.CSharp
|
|||||||
static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
|
static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
|
||||||
{
|
{
|
||||||
bool prefixAssembly = true;
|
bool prefixAssembly = true;
|
||||||
if (cx.Extractor.Standalone) prefixAssembly = false;
|
|
||||||
if (named.ContainingAssembly is null) prefixAssembly = false;
|
if (named.ContainingAssembly is null) prefixAssembly = false;
|
||||||
|
|
||||||
if (named.IsTupleType)
|
if (named.IsTupleType)
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ namespace Semmle.Extraction
|
|||||||
#if DEBUG_LABELS
|
#if DEBUG_LABELS
|
||||||
using (var id = new StringWriter())
|
using (var id = new StringWriter())
|
||||||
{
|
{
|
||||||
entity.WriteId(id);
|
entity.WriteQuotedId(id);
|
||||||
CheckEntityHasUniqueLabel(id.ToString(), entity);
|
CheckEntityHasUniqueLabel(id.ToString(), entity);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -270,6 +270,8 @@ namespace Semmle.Extraction
|
|||||||
TrapWriter = trapWriter;
|
TrapWriter = trapWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool FromSource => Scope.FromSource;
|
||||||
|
|
||||||
public bool IsGlobalContext => Scope.IsGlobalScope;
|
public bool IsGlobalContext => Scope.IsGlobalScope;
|
||||||
|
|
||||||
public readonly ICommentGenerator CommentGenerator = new CommentProcessor();
|
public readonly ICommentGenerator CommentGenerator = new CommentProcessor();
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ namespace Semmle.Extraction
|
|||||||
bool InFileScope(string path);
|
bool InFileScope(string path);
|
||||||
|
|
||||||
bool IsGlobalScope { get; }
|
bool IsGlobalScope { get; }
|
||||||
|
|
||||||
|
bool FromSource { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,6 +51,8 @@ namespace Semmle.Extraction
|
|||||||
public bool InScope(ISymbol symbol) =>
|
public bool InScope(ISymbol symbol) =>
|
||||||
SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) ||
|
SymbolEqualityComparer.Default.Equals(symbol.ContainingAssembly, assembly) ||
|
||||||
SymbolEqualityComparer.Default.Equals(symbol, assembly);
|
SymbolEqualityComparer.Default.Equals(symbol, assembly);
|
||||||
|
|
||||||
|
public bool FromSource => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -68,5 +72,7 @@ namespace Semmle.Extraction
|
|||||||
public bool InFileScope(string path) => path == sourceTree.FilePath;
|
public bool InFileScope(string path) => path == sourceTree.FilePath;
|
||||||
|
|
||||||
public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == sourceTree);
|
public bool InScope(ISymbol symbol) => symbol.Locations.Any(loc => loc.SourceTree == sourceTree);
|
||||||
|
|
||||||
|
public bool FromSource => true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,13 +50,15 @@ namespace Semmle.Extraction
|
|||||||
/// Record a new error type.
|
/// Record a new error type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fqn">The display name of the type, qualified where possible.</param>
|
/// <param name="fqn">The display name of the type, qualified where possible.</param>
|
||||||
void MissingType(string fqn);
|
/// <param name="fromSource">If the missing type was referenced from a source file.</param>
|
||||||
|
void MissingType(string fqn, bool fromSource);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Record an unresolved `using namespace` directive.
|
/// Record an unresolved `using namespace` directive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="fqn">The full name of the namespace.</param>
|
/// <param name="fqn">The full name of the namespace.</param>
|
||||||
void MissingNamespace(string fqn);
|
/// <param name="fromSource">If the missing namespace was referenced from a source file.</param>
|
||||||
|
void MissingNamespace(string fqn, bool fromSource);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of missing types.
|
/// The list of missing types.
|
||||||
@@ -167,16 +169,22 @@ namespace Semmle.Extraction
|
|||||||
readonly ISet<string> missingTypes = new SortedSet<string>();
|
readonly ISet<string> missingTypes = new SortedSet<string>();
|
||||||
readonly ISet<string> missingNamespaces = new SortedSet<string>();
|
readonly ISet<string> missingNamespaces = new SortedSet<string>();
|
||||||
|
|
||||||
public void MissingType(string fqn)
|
public void MissingType(string fqn, bool fromSource)
|
||||||
{
|
{
|
||||||
lock (mutex)
|
if (fromSource)
|
||||||
missingTypes.Add(fqn);
|
{
|
||||||
|
lock (mutex)
|
||||||
|
missingTypes.Add(fqn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MissingNamespace(string fqdn)
|
public void MissingNamespace(string fqdn, bool fromSource)
|
||||||
{
|
{
|
||||||
lock (mutex)
|
if (fromSource)
|
||||||
missingNamespaces.Add(fqdn);
|
{
|
||||||
|
lock (mutex)
|
||||||
|
missingNamespaces.Add(fqdn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope)
|
public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -9,20 +9,19 @@ namespace Semmle.Util
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="Key"></typeparam>
|
/// <typeparam name="Key"></typeparam>
|
||||||
/// <typeparam name="Value"></typeparam>
|
/// <typeparam name="Value"></typeparam>
|
||||||
public class ActionMap<Key, Value>
|
public class ActionMap<Key, Value> where Key : notnull
|
||||||
{
|
{
|
||||||
public void Add(Key key, Value value)
|
public void Add(Key key, Value value)
|
||||||
{
|
{
|
||||||
Action<Value> a;
|
|
||||||
if (actions.TryGetValue(key, out a))
|
if (actions.TryGetValue(key, out var a))
|
||||||
a(value);
|
a(value);
|
||||||
values[key] = value;
|
values[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnAdd(Key key, Action<Value> action)
|
public void OnAdd(Key key, Action<Value> action)
|
||||||
{
|
{
|
||||||
Action<Value> a;
|
if (actions.TryGetValue(key, out var a))
|
||||||
if (actions.TryGetValue(key, out a))
|
|
||||||
{
|
{
|
||||||
actions[key] = a + action;
|
actions[key] = a + action;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,8 +127,8 @@ namespace Semmle.Util
|
|||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
string name = Path.GetFileName(path);
|
var name = Path.GetFileName(path);
|
||||||
string parentPath = cache.GetCanonicalPath(parent.FullName);
|
var parentPath = cache.GetCanonicalPath(parent.FullName);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string[] entries = Directory.GetFileSystemEntries(parentPath, name);
|
string[] entries = Directory.GetFileSystemEntries(parentPath, name);
|
||||||
@@ -313,14 +313,15 @@ namespace Semmle.Util
|
|||||||
/// <returns>The canonical path.</returns>
|
/// <returns>The canonical path.</returns>
|
||||||
public string GetCanonicalPath(string path)
|
public string GetCanonicalPath(string path)
|
||||||
{
|
{
|
||||||
string canonicalPath;
|
|
||||||
lock (cache)
|
lock (cache)
|
||||||
if (!cache.TryGetValue(path, out canonicalPath))
|
{
|
||||||
|
if (!cache.TryGetValue(path, out var canonicalPath))
|
||||||
{
|
{
|
||||||
canonicalPath = pathStrategy.GetCanonicalPath(path, this);
|
canonicalPath = pathStrategy.GetCanonicalPath(path, this);
|
||||||
AddToCache(path, canonicalPath);
|
AddToCache(path, canonicalPath);
|
||||||
}
|
}
|
||||||
return canonicalPath;
|
return canonicalPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Semmle.Util
|
|||||||
var found = false;
|
var found = false;
|
||||||
foreach (var arg in commandLineArguments.Where(arg => arg.StartsWith('@')).Select(arg => arg.Substring(1)))
|
foreach (var arg in commandLineArguments.Where(arg => arg.StartsWith('@')).Select(arg => arg.Substring(1)))
|
||||||
{
|
{
|
||||||
string line;
|
string? line;
|
||||||
using (StreamReader file = new StreamReader(arg))
|
using (StreamReader file = new StreamReader(arg))
|
||||||
while ((line = file.ReadLine()) != null)
|
while ((line = file.ReadLine()) != null)
|
||||||
textWriter.WriteLine(line);
|
textWriter.WriteLine(line);
|
||||||
|
|||||||
@@ -9,10 +9,9 @@ namespace Semmle.Util
|
|||||||
/// dictionary. If a list does not already exist, a new list is
|
/// dictionary. If a list does not already exist, a new list is
|
||||||
/// created.
|
/// created.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void AddAnother<T1, T2>(this Dictionary<T1, List<T2>> dict, T1 key, T2 element)
|
public static void AddAnother<T1, T2>(this Dictionary<T1, List<T2>> dict, T1 key, T2 element) where T1:notnull
|
||||||
{
|
{
|
||||||
List<T2> list;
|
if (!dict.TryGetValue(key, out var list))
|
||||||
if (!dict.TryGetValue(key, out list))
|
|
||||||
{
|
{
|
||||||
list = new List<T2>();
|
list = new List<T2>();
|
||||||
dict[key] = list;
|
dict[key] = list;
|
||||||
|
|||||||
34
csharp/extractor/Semmle.Util/FileRenamer.cs
Normal file
34
csharp/extractor/Semmle.Util/FileRenamer.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Semmle.Util
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility to temporarily rename a set of files.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class FileRenamer : IDisposable
|
||||||
|
{
|
||||||
|
readonly string[] files;
|
||||||
|
const string suffix = ".codeqlhidden";
|
||||||
|
|
||||||
|
public FileRenamer(IEnumerable<FileInfo> oldFiles)
|
||||||
|
{
|
||||||
|
files = oldFiles.Select(f => f.FullName).ToArray();
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
File.Move(file, file + suffix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
File.Move(file + suffix, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ namespace Semmle.Util
|
|||||||
///
|
///
|
||||||
/// Returns <code>null</code> of no path can be found.
|
/// Returns <code>null</code> of no path can be found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string FindProgramOnPath(string prog)
|
public static string? FindProgramOnPath(string prog)
|
||||||
{
|
{
|
||||||
var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator);
|
var paths = Environment.GetEnvironmentVariable("PATH")?.Split(Path.PathSeparator);
|
||||||
string[] exes;
|
string[] exes;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Semmle.Util
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
///
|
///
|
||||||
/// <typeparam name="T">The value type.</typeparam>
|
/// <typeparam name="T">The value type.</typeparam>
|
||||||
public class FuzzyDictionary<T>
|
public class FuzzyDictionary<T> where T:class
|
||||||
{
|
{
|
||||||
// All data items indexed by the "base string" (stripped of numbers)
|
// All data items indexed by the "base string" (stripped of numbers)
|
||||||
readonly Dictionary<string, List<KeyValuePair<string, T>>> index = new Dictionary<string, List<KeyValuePair<string, T>>>();
|
readonly Dictionary<string, List<KeyValuePair<string, T>>> index = new Dictionary<string, List<KeyValuePair<string, T>>>();
|
||||||
@@ -61,7 +61,7 @@ namespace Semmle.Util
|
|||||||
/// <param name="v1">Vector 1</param>
|
/// <param name="v1">Vector 1</param>
|
||||||
/// <param name="v2">Vector 2</param>
|
/// <param name="v2">Vector 2</param>
|
||||||
/// <returns>The Hamming Distance.</returns>
|
/// <returns>The Hamming Distance.</returns>
|
||||||
static int HammingDistance<U>(IEnumerable<U> v1, IEnumerable<U> v2)
|
static int HammingDistance<U>(IEnumerable<U> v1, IEnumerable<U> v2) where U: notnull
|
||||||
{
|
{
|
||||||
return v1.Zip(v2, (x, y) => x.Equals(y) ? 0 : 1).Sum();
|
return v1.Zip(v2, (x, y) => x.Equals(y) ? 0 : 1).Sum();
|
||||||
}
|
}
|
||||||
@@ -72,11 +72,10 @@ namespace Semmle.Util
|
|||||||
/// <param name="query">The query string.</param>
|
/// <param name="query">The query string.</param>
|
||||||
/// <param name="distance">The distance between the query string and the stored string.</param>
|
/// <param name="distance">The distance between the query string and the stored string.</param>
|
||||||
/// <returns>The best match, or null (default).</returns>
|
/// <returns>The best match, or null (default).</returns>
|
||||||
public T FindMatch(string query, out int distance)
|
public T? FindMatch(string query, out int distance)
|
||||||
{
|
{
|
||||||
string root = StripDigits(query);
|
string root = StripDigits(query);
|
||||||
List<KeyValuePair<string, T>> list;
|
if (!index.TryGetValue(root, out var list))
|
||||||
if (!index.TryGetValue(root, out list))
|
|
||||||
{
|
{
|
||||||
distance = 0;
|
distance = 0;
|
||||||
return default(T);
|
return default(T);
|
||||||
@@ -93,9 +92,9 @@ namespace Semmle.Util
|
|||||||
/// <param name="distance">The distance function.</param>
|
/// <param name="distance">The distance function.</param>
|
||||||
/// <param name="bestDistance">The distance between the query and the stored string.</param>
|
/// <param name="bestDistance">The distance between the query and the stored string.</param>
|
||||||
/// <returns>The stored value.</returns>
|
/// <returns>The stored value.</returns>
|
||||||
static T BestMatch(string query, IEnumerable<KeyValuePair<string, T>> candidates, Func<string, string, int> distance, out int bestDistance)
|
static T? BestMatch(string query, IEnumerable<KeyValuePair<string, T>> candidates, Func<string, string, int> distance, out int bestDistance)
|
||||||
{
|
{
|
||||||
T bestMatch = default(T);
|
T? bestMatch = default(T);
|
||||||
bestDistance = 0;
|
bestDistance = 0;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ namespace Semmle.Util
|
|||||||
/// <typeparam name="T">The type of the item.</typeparam>
|
/// <typeparam name="T">The type of the item.</typeparam>
|
||||||
/// <param name="items">The list of items to hash.</param>
|
/// <param name="items">The list of items to hash.</param>
|
||||||
/// <returns>The hash code.</returns>
|
/// <returns>The hash code.</returns>
|
||||||
public static int SequenceHash<T>(this IEnumerable<T> items)
|
public static int SequenceHash<T>(this IEnumerable<T> items) where T: notnull
|
||||||
{
|
{
|
||||||
int h = 0;
|
int h = 0;
|
||||||
foreach (var i in items)
|
foreach (var i in items)
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ namespace Semmle.Util
|
|||||||
//#################### PUBLIC METHODS ####################
|
//#################### PUBLIC METHODS ####################
|
||||||
#region
|
#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;
|
return rhs != null && Total == rhs.Total && Code == rhs.Code && Comment == rhs.Comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ namespace Semmle.Util.Logging
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(outputFile);
|
string? dir = Path.GetDirectoryName(outputFile);
|
||||||
if (dir.Length > 0 && !System.IO.Directory.Exists(dir))
|
if (!string.IsNullOrEmpty(dir) && !System.IO.Directory.Exists(dir))
|
||||||
Directory.CreateDirectory(dir);
|
Directory.CreateDirectory(dir);
|
||||||
writer = new PidStreamWriter(new FileStream(outputFile, FileMode.Append, FileAccess.Write,
|
writer = new PidStreamWriter(new FileStream(outputFile, FileMode.Append, FileAccess.Write,
|
||||||
FileShare.ReadWrite, 8192));
|
FileShare.ReadWrite, 8192));
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Semmle.Util
|
|||||||
|
|
||||||
private readonly string prefix = "[" + Process.GetCurrentProcess().Id + "] ";
|
private readonly string prefix = "[" + Process.GetCurrentProcess().Id + "] ";
|
||||||
|
|
||||||
public override void WriteLine(string value)
|
public override void WriteLine(string? value)
|
||||||
{
|
{
|
||||||
lock (mutex)
|
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();
|
readonly object mutex = new object();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Semmle.Util
|
|||||||
stdout = new List<string>();
|
stdout = new List<string>();
|
||||||
using (var process = Process.Start(pi))
|
using (var process = Process.Start(pi))
|
||||||
{
|
{
|
||||||
string s;
|
string? s;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
s = process.StandardOutput.ReadLine();
|
s = process.StandardOutput.ReadLine();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
<RootNamespace>Semmle.Util</RootNamespace>
|
<RootNamespace>Semmle.Util</RootNamespace>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ namespace Semmle.Util
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The shared object to which different parts of the code want to refer.
|
/// The shared object to which different parts of the code want to refer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Obj { get; set; }
|
public T? Obj { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
csharp/extractor/Semmle.Util/TemporaryDirectory.cs
Normal file
30
csharp/extractor/Semmle.Util/TemporaryDirectory.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Semmle.Util
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A temporary directory that is created within the system temp directory.
|
||||||
|
/// When this object is disposed, the directory is deleted.
|
||||||
|
/// </summary>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
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.frameworks.system.Xml
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.commons.Util
|
import semmle.code.csharp.commons.Util
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.dataflow.flowsources.Local
|
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||||
import semmle.code.csharp.dataflow.TaintTracking
|
import semmle.code.csharp.dataflow.TaintTracking
|
||||||
import semmle.code.csharp.frameworks.Format
|
import semmle.code.csharp.frameworks.Format
|
||||||
import DataFlow::PathGraph
|
import DataFlow::PathGraph
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
import semmle.code.csharp.security.SensitiveActions
|
import semmle.code.csharp.security.SensitiveActions
|
||||||
import semmle.code.csharp.security.dataflow.XSS
|
import semmle.code.csharp.security.dataflow.flowsinks.Remote
|
||||||
import semmle.code.csharp.security.dataflow.Email
|
|
||||||
import semmle.code.csharp.frameworks.system.data.Common
|
import semmle.code.csharp.frameworks.system.data.Common
|
||||||
import semmle.code.csharp.frameworks.System
|
import semmle.code.csharp.frameworks.System
|
||||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||||
@@ -42,11 +41,7 @@ class TaintTrackingConfiguration extends TaintTracking::Configuration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
override predicate isSink(DataFlow::Node sink) { sink instanceof RemoteFlowSink }
|
||||||
sink instanceof XSS::Sink
|
|
||||||
or
|
|
||||||
sink instanceof Email::Sink
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink
|
from TaintTrackingConfiguration configuration, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
import semmle.code.csharp.frameworks.System
|
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
|
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) {
|
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
||||||
// Do not flow through Message
|
// Do not flow through Message
|
||||||
|
|||||||
@@ -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
|
||||||
import semmle.code.csharp.frameworks.system.web.UI
|
import semmle.code.csharp.frameworks.system.web.UI
|
||||||
import semmle.code.csharp.security.dataflow.SqlInjection
|
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.dataflow.UrlRedirect
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
|
import semmle.code.csharp.dataflow.DataFlow2::DataFlow2
|
||||||
@@ -114,7 +114,7 @@ module EncodingConfigurations {
|
|||||||
|
|
||||||
override string getKind() { result = "HTML expression" }
|
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 }
|
override predicate isPossibleEncodedValue(Expr e) { e instanceof HtmlSanitizedExpr }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import semmle.code.csharp.frameworks.Test
|
|||||||
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
import semmle.code.csharp.dataflow.DataFlow::DataFlow::PathGraph
|
||||||
|
|
||||||
module Random {
|
module Random {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.security.SensitiveActions
|
import semmle.code.csharp.security.SensitiveActions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
4
csharp/ql/src/codeql-suites/csharp-code-scanning.qls
Normal file
4
csharp/ql/src/codeql-suites/csharp-code-scanning.qls
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- description: Standard Code Scanning queries for C#
|
||||||
|
- qlpack: codeql-csharp
|
||||||
|
- apply: code-scanning-selectors.yml
|
||||||
|
from: codeql-suite-helpers
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
|
* DEPRECATED.
|
||||||
|
*
|
||||||
* Provides classes representing data flow sources for parameters of public callables.
|
* Provides classes representing data flow sources for parameters of public callables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
private import semmle.code.csharp.frameworks.WCF
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parameter of a public callable, for example `p` in
|
* A parameter of a public callable, for example `p` in
|
||||||
|
|||||||
@@ -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
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
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" }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -388,7 +388,12 @@ library class PropertyAccessExpr extends Expr, @property_access_expr {
|
|||||||
/** Gets the target of this property access. */
|
/** Gets the target of this property access. */
|
||||||
Property getProperty() { expr_access(this, result) }
|
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)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,10 +5,10 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module CleartextStorage {
|
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.frameworks.system.Web
|
||||||
import semmle.code.csharp.security.SensitiveActions
|
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.
|
* A data flow source for cleartext storage of sensitive information.
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module CodeInjection {
|
module CodeInjection {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.dataflow.flowsources.Local
|
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||||
import semmle.code.csharp.frameworks.system.codedom.Compiler
|
import semmle.code.csharp.frameworks.system.codedom.Compiler
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module CommandInjection {
|
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.frameworks.system.Diagnostics
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import csharp
|
|||||||
module UserControlledBypassOfSensitiveMethod {
|
module UserControlledBypassOfSensitiveMethod {
|
||||||
import semmle.code.csharp.controlflow.Guards
|
import semmle.code.csharp.controlflow.Guards
|
||||||
import semmle.code.csharp.controlflow.BasicBlocks
|
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
|
||||||
import semmle.code.csharp.frameworks.system.Net
|
import semmle.code.csharp.frameworks.system.Net
|
||||||
import semmle.code.csharp.security.SensitiveActions
|
import semmle.code.csharp.security.SensitiveActions
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module ExposureOfPrivateInformation {
|
module ExposureOfPrivateInformation {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.security.sinks.ExternalLocationSink
|
import semmle.code.csharp.security.dataflow.flowsinks.ExternalLocationSink
|
||||||
import semmle.code.csharp.security.PrivateData
|
import semmle.code.csharp.security.PrivateData
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module LDAPInjection {
|
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
|
||||||
import semmle.code.csharp.frameworks.system.directoryservices.Protocols
|
import semmle.code.csharp.frameworks.system.directoryservices.Protocols
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module LogForging {
|
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
|
||||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||||
import semmle.code.csharp.security.Sanitizers
|
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.
|
* A data flow source for untrusted user input used in log entries.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module MissingXMLValidation {
|
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.frameworks.system.Xml
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import csharp
|
|||||||
|
|
||||||
module ReDoS {
|
module ReDoS {
|
||||||
private import semmle.code.csharp.dataflow.DataFlow2
|
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.frameworks.system.text.RegularExpressions
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module RegexInjection {
|
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.frameworks.system.text.RegularExpressions
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module ResourceInjection {
|
module ResourceInjection {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.dataflow.flowsources.Local
|
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||||
import semmle.code.csharp.frameworks.system.Data
|
import semmle.code.csharp.frameworks.system.Data
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module SqlInjection {
|
module SqlInjection {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
import semmle.code.csharp.dataflow.flowsources.Local
|
import semmle.code.csharp.security.dataflow.flowsources.Local
|
||||||
import semmle.code.csharp.frameworks.Sql
|
import semmle.code.csharp.frameworks.Sql
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import csharp
|
|||||||
|
|
||||||
module TaintedPath {
|
module TaintedPath {
|
||||||
import semmle.code.csharp.controlflow.Guards
|
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.IO
|
||||||
import semmle.code.csharp.frameworks.system.Web
|
import semmle.code.csharp.frameworks.system.Web
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module UnsafeDeserialization {
|
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
|
private import semmle.code.csharp.serialization.Deserializers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module UrlRedirect {
|
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.controlflow.Guards
|
||||||
import semmle.code.csharp.frameworks.system.Web
|
import semmle.code.csharp.frameworks.system.Web
|
||||||
import semmle.code.csharp.frameworks.system.web.Mvc
|
import semmle.code.csharp.frameworks.system.web.Mvc
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module XMLEntityInjection {
|
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
|
||||||
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
import semmle.code.csharp.frameworks.system.text.RegularExpressions
|
||||||
import semmle.code.csharp.security.xml.InsecureXML
|
import semmle.code.csharp.security.xml.InsecureXML
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module XPathInjection {
|
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.XPath
|
||||||
import semmle.code.csharp.frameworks.system.Xml
|
import semmle.code.csharp.frameworks.system.Xml
|
||||||
import semmle.code.csharp.security.Sanitizers
|
import semmle.code.csharp.security.Sanitizers
|
||||||
|
|||||||
@@ -6,17 +6,14 @@
|
|||||||
import csharp
|
import csharp
|
||||||
|
|
||||||
module XSS {
|
module XSS {
|
||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.asp.AspNet
|
||||||
import semmle.code.csharp.frameworks.microsoft.AspNetCore
|
|
||||||
import semmle.code.csharp.frameworks.system.Net
|
import semmle.code.csharp.frameworks.system.Net
|
||||||
import semmle.code.csharp.frameworks.system.Web
|
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
|
||||||
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.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
|
* 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.
|
* 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() }
|
string explanation() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,78 +166,21 @@ module XSS {
|
|||||||
UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr }
|
UrlEncodeSanitizer() { this.getExpr() instanceof UrlSanitizedExpr }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A sink where the value of the expression may be rendered as HTML. */
|
private class HtmlSinkSink extends Sink {
|
||||||
abstract class HtmlSink extends DataFlow::Node { }
|
HtmlSinkSink() { this instanceof HtmlSink }
|
||||||
|
|
||||||
/**
|
override string explanation() {
|
||||||
* An expression that is used as an argument to an XSS sink method on
|
this instanceof WebPageWriteLiteralSink and
|
||||||
* `HttpResponse`.
|
result = "System.Web.WebPages.WebPage.WriteLiteral() method"
|
||||||
*/
|
or
|
||||||
private class HttpResponseSink extends Sink, HtmlSink {
|
this instanceof WebPageWriteLiteralToSink and
|
||||||
HttpResponseSink() {
|
result = "System.Web.WebPages.WebPage.WriteLiteralTo() method"
|
||||||
exists(Method m, SystemWebHttpResponseClass responseClass |
|
or
|
||||||
m = responseClass.getAWriteMethod() or
|
this instanceof MicrosoftAspNetCoreMvcHtmlHelperRawSink and
|
||||||
m = responseClass.getAWriteFileMethod() or
|
result = "Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper.Raw() method"
|
||||||
m = responseClass.getATransmitFileMethod() or
|
or
|
||||||
m = responseClass.getABinaryWriteMethod()
|
this instanceof MicrosoftAspNetRazorPageWriteLiteralSink and
|
||||||
|
|
result = "Microsoft.AspNetCore.Mvc.Razor.RazorPageBase.WriteLiteral() method"
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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
|
* An expression that is used as an argument to an XSS sink setter, on
|
||||||
* a class within the `System.Web.UI` namespace.
|
* 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`.
|
* 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
|
* 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`.
|
* An expression passed as the `content` argument to the constructor of `StringContent`.
|
||||||
*/
|
*/
|
||||||
@@ -529,75 +412,6 @@ module XSS {
|
|||||||
).getArgumentForName("content")
|
).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) {
|
private Type getMemberType(Member m) {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
/** Provides data flow sinks for sending email. */
|
/** Provides data flow sinks for sending email. */
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
|
private import Remote
|
||||||
private import semmle.code.csharp.frameworks.system.net.Mail
|
private import semmle.code.csharp.frameworks.system.net.Mail
|
||||||
|
|
||||||
|
/** Provides sinks for emails. */
|
||||||
module Email {
|
module Email {
|
||||||
/** A data flow sink for sending 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`. */
|
/** A data flow sink for sending email via `System.Net.Mail.MailMessage`. */
|
||||||
class MailMessageSink extends Sink {
|
class MailMessageSink extends Sink {
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import csharp
|
import csharp
|
||||||
|
private import Remote
|
||||||
private import semmle.code.csharp.commons.Loggers
|
private import semmle.code.csharp.commons.Loggers
|
||||||
private import semmle.code.csharp.frameworks.system.Web
|
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.
|
* An expression set as a value on a cookie instance.
|
||||||
*/
|
*/
|
||||||
class CookieStorageSink extends ExternalLocationSink {
|
class CookieStorageSink extends ExternalLocationSink, RemoteFlowSink {
|
||||||
CookieStorageSink() {
|
CookieStorageSink() {
|
||||||
exists(Expr e | e = this.getExpr() |
|
exists(Expr e | e = this.getExpr() |
|
||||||
e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value")
|
e = any(SystemWebHttpCookie cookie).getAConstructor().getACall().getArgumentForName("value")
|
||||||
@@ -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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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" }
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import semmle.code.csharp.dataflow.flowsources.Remote
|
import semmle.code.csharp.security.dataflow.flowsources.Remote
|
||||||
|
|
||||||
from RemoteFlowSource source
|
from RemoteFlowSource source
|
||||||
select source, source.getSourceType()
|
select source, source.getSourceType()
|
||||||
|
|||||||
@@ -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 (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: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: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:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Call (unknown target) |
|
||||||
| ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression |
|
| 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:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" |
|
| 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 (unknown target) |
|
||||||
| ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | call to method |
|
| 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 |
|
| 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: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: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: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:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Call (unknown target) |
|
||||||
| 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 | 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 | ... = ... |
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
| errors.cs:43:21:43:28 | errors.cs:43:21:43:28 | object creation of type C1 | C1 |
|
| 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: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: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 |
|
| errors.cs:53:17:53:25 | errors.cs:53:17:53:25 | object creation of type C2 | none |
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user