mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Merge branch 'main' into mathiasvp/read-step-without-memory-operands
This commit is contained in:
@@ -4,6 +4,6 @@
|
||||
"slevesque.vscode-zipexplorer"
|
||||
],
|
||||
"settings": {
|
||||
"codeQL.experimentalBqrsParsing": true
|
||||
"codeQL.runningQueries.memory": 2048
|
||||
}
|
||||
}
|
||||
|
||||
11
.github/workflows/labeler.yml
vendored
Normal file
11
.github/workflows/labeler.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v2
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
@@ -9,7 +9,7 @@ You can use the [interactive query console](https://lgtm.com/help/lgtm/using-que
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
|
||||
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/main/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The models library now models some taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
|
||||
* The models library now models many taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
|
||||
* The models library now models many more taint flows through `std::string`.
|
||||
* The `SimpleRangeAnalysis` library now supports multiplications of the form
|
||||
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.
|
||||
|
||||
@@ -21,6 +21,10 @@ The following changes in version 1.26 affect C# analysis in all applications.
|
||||
* Partial method bodies are extracted. Previously, partial method bodies were skipped completely.
|
||||
* Inferring the lengths of implicitely sized arrays is fixed. Previously, multidimensional arrays were always extracted with the same length for
|
||||
each dimension. With the fix, the array sizes `2` and `1` are extracted for `new int[,]{{1},{2}}`. Previously `2` and `2` were extracted.
|
||||
* The extractor is now assembly-insensitive by default. This means that two entities with the same
|
||||
fully-qualified name are now mapped to the same entity in the resulting database, regardless of
|
||||
whether they belong to different assemblies. Assembly sensitivity can be reenabled by passing
|
||||
`--assemblysensitivetrap` to the extractor.
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
|
||||
| Potentially unsafe external link (`js/unsafe-external-link`) | Fewer results | This query no longer flags URLs constructed using a template system where only the hash or query part of the URL is dynamic. |
|
||||
| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. |
|
||||
| Ambiguous HTML id attribute (`js/duplicate-html-id`) | Results no longer shown | Precision tag reduced to "low". The query is no longer run by default. |
|
||||
| Unused loop iteration variable (`js/unused-loop-variable`) | Fewer results | This query no longer flags variables in a destructuring array assignment that are not the last variable in the destructed array. |
|
||||
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
@@ -335,5 +335,50 @@
|
||||
"java/ql/src/semmle/code/xml/XML.qll",
|
||||
"javascript/ql/src/semmle/javascript/XML.qll",
|
||||
"python/ql/src/semmle/python/xml/XML.qll"
|
||||
],
|
||||
"DuplicationProblems.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/DuplicationProblems.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/DuplicationProblems.qhelp",
|
||||
"javascript/ql/src/Metrics/DuplicationProblems.qhelp",
|
||||
"python/ql/src/Metrics/DuplicationProblems.qhelp"
|
||||
],
|
||||
"CommentedOutCodeQuery.qhelp": [
|
||||
"cpp/ql/src/Documentation/CommentedOutCodeQuery.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeQuery.qhelp",
|
||||
"csharp/ql/src/Bad Practices/Comments/CommentedOutCodeQuery.qhelp",
|
||||
"java/ql/src/Violations of Best Practice/Comments/CommentedOutCodeQuery.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeQuery.qhelp"
|
||||
],
|
||||
"FLinesOfCodeReferences.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FLinesOfCodeReferences.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfCodeReferences.qhelp"
|
||||
],
|
||||
"FCommentRatioCommon.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FCommentRatioCommon.qhelp",
|
||||
"javascript/ql/src/Metrics/FCommentRatioCommon.qhelp"
|
||||
],
|
||||
"FLinesOfCodeOverview.qhelp": [
|
||||
"java/ql/src/Metrics/Files/FLinesOfCodeOverview.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfCodeOverview.qhelp"
|
||||
],
|
||||
"CommentedOutCodeMetricOverview.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"java/ql/src/Metrics/Files/CommentedOutCodeMetricOverview.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeMetricOverview.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeMetricOverview.qhelp"
|
||||
],
|
||||
"FLinesOfDuplicatedCodeCommon.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"java/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.qhelp",
|
||||
"python/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.qhelp"
|
||||
],
|
||||
"CommentedOutCodeReferences.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"csharp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"java/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
|
||||
"javascript/ql/src/Comments/CommentedOutCodeReferences.qhelp",
|
||||
"python/ql/src/Lexical/CommentedOutCodeReferences.qhelp"
|
||||
]
|
||||
}
|
||||
|
||||
11
cpp/ql/src/Critical/aliasAnalysisWarning.qhelp
Normal file
11
cpp/ql/src/Critical/aliasAnalysisWarning.qhelp
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute the exact value of the variable without running the program with all possible input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
12
cpp/ql/src/Critical/callGraphWarning.qhelp
Normal file
12
cpp/ql/src/Critical/callGraphWarning.qhelp
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute which function is actually called in a virtual call,
|
||||
or a call through a pointer, without running the program with all possible input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
13
cpp/ql/src/Critical/dataFlowWarning.qhelp
Normal file
13
cpp/ql/src/Critical/dataFlowWarning.qhelp
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program.
|
||||
It is not possible in general to compute the actual branch taken in conditional statements such
|
||||
as "if" without running the program with all possible input data. This means that it is not possible
|
||||
to determine if a particular statement is going to be executed.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
11
cpp/ql/src/Critical/pointsToWarning.qhelp
Normal file
11
cpp/ql/src/Critical/pointsToWarning.qhelp
Normal file
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<warning>
|
||||
This check is an approximation, so some results may not be actual defects in the program. It is not possible
|
||||
in general to compute the values of pointers without running the program with all input data.
|
||||
</warning>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -3,5 +3,5 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="CommentedOutCodeQuery.qhelp" />
|
||||
<include src="CommentedOutCodeReferences.qhelp" />
|
||||
<include src="../Metrics/Files/CommentedOutCodeReferences.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
25
cpp/ql/src/Documentation/CommentedOutCodeQuery.qhelp
Normal file
25
cpp/ql/src/Documentation/CommentedOutCodeQuery.qhelp
Normal file
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Commented-out code is distracting and confusing for developers who read the surrounding code,
|
||||
and its significance is often unclear. It will not get compiled or tested when the code around
|
||||
it changes, so it's likely to break over time. For these reasons, commented-out code should be
|
||||
avoided.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Remove or reinstate the commented-out code. If you want to include a snippet of example code
|
||||
in a comment, consider enclosing it in quotes or marking it up as appropriate for the source
|
||||
language.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
This metric counts the number of lines of commented-out code in each file. Large amounts of
|
||||
commented-out code often indicate poorly maintained code.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
</qhelp>
|
||||
12
cpp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp
Normal file
12
cpp/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<references>
|
||||
|
||||
<li>Mark Needham: <a href="http://www.markhneedham.com/blog/2009/01/17/the-danger-of-commenting-out-code/">The danger of commenting out code</a>.</li>
|
||||
<li>Los Techies: <a href="http://lostechies.com/rodpaddock/2010/12/29/commented-code-technical-debt">Commented Code == Technical Debt</a>.</li>
|
||||
<li>High Integrity C++ Coding Standard: <a href="http://www.codingstandard.com/rule/2-3-2-do-not-comment-out-code/">2.3.2 Do not comment out code</a>.</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
16
cpp/ql/src/Metrics/Files/DuplicationProblems.qhelp
Normal file
16
cpp/ql/src/Metrics/Files/DuplicationProblems.qhelp
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Duplicated code increases overall code size, making the code base
|
||||
harder to maintain and harder to understand. It also becomes harder to fix bugs,
|
||||
since a programmer applying a fix to one copy has to always remember to update
|
||||
other copies accordingly. Finally, code duplication is generally an indication of
|
||||
a poorly designed or hastily written code base, which typically suffers from other
|
||||
problems as well.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
</qhelp>
|
||||
35
cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp
Normal file
35
cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.qhelp
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
|
||||
<p>
|
||||
This metric measures the number of lines in a file that are contained within a block that is duplicated elsewhere. These lines may include code, comments and whitespace, and the duplicate block may be in this file or in another file.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A file that contains many lines that are duplicated within the code base is problematic
|
||||
for a number of reasons.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<include src="DuplicationProblems.qhelp" />
|
||||
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
Refactor files with lots of duplicated code to extract the common code into
|
||||
a shared library or module.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<references>
|
||||
|
||||
|
||||
<li>Wikipedia: <a href="http://en.wikipedia.org/wiki/Duplicate_code">Duplicate code</a>.</li>
|
||||
<li>M. Fowler, <em>Refactoring</em>. Addison-Wesley, 1999.</li>
|
||||
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights calls to the standard library functions <code>abort, exit, getenv</code> and <code>system</code>.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query ensures that all operators with opposites (e.g. == and !=) are both defined, and
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights return statements that return pointers to an object allocated on the stack. The lifetime
|
||||
@@ -18,7 +18,7 @@ memory after the function has already returned will have undefined results.
|
||||
|
||||
|
||||
<!-- Mention how the results could be probabilistic (uses pointsto) -->
|
||||
<include src="pointsToWarning.qhelp" />
|
||||
<include src="../../Critical/pointsToWarning.qhelp" />
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
@@ -12,7 +12,7 @@ calling convention for x86, it would be whatever value was in the AX/EAX registe
|
||||
assuming the function had a non-float return type that can fit in a machine word.
|
||||
</p>
|
||||
|
||||
<include src="dataFlowWarning.qhelp" />
|
||||
<include src="../../Critical/dataFlowWarning.qhelp" />
|
||||
|
||||
<!--/*FALSEPOSITIVE_WARNING*/-->
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights identifiers in an inner scope that hide (have the same name as) an identifier in an outer scope.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights variables with the <code>register</code> storage class specifier. Modern compilers are now capable of
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights portions of code that can expose the floating point implementation of the underlying
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query highlights string literals that are assigned to a non-<code>const</code> variable. String literals
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query finds bit fields with members that are not explicitly declared to be unsigned.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>
|
||||
This query finds unsigned values that are being negated. Behavior is undefined in such cases.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<overview>
|
||||
|
||||
<!-- Mention that this rule may not be applicable in projects that don't follow the JSF standard. -->
|
||||
<include src="cpp/jsfNote.qhelp" />
|
||||
<include src="../jsfNote.qhelp" />
|
||||
|
||||
<p>Use of goto statements makes code more difficult to understand and maintain. Consequently, the use
|
||||
of goto statements is deprecated except as a mechanism for breaking out of multiple nested loops.
|
||||
|
||||
18
cpp/ql/src/jsf/jsfNote.qhelp
Normal file
18
cpp/ql/src/jsf/jsfNote.qhelp
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<fragment>
|
||||
<p>
|
||||
This query is part of a suite that tests code against
|
||||
the <em>Joint Strike Fighter Air Vehicle C++ Coding Standard</em> (JSF).
|
||||
Alerts reported by this query highlight code that may break the
|
||||
JSF rule listed in the References section.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The JSF rule this query tests is likely to be too strict for projects
|
||||
that do not follow the JSF standard.
|
||||
</p>
|
||||
</fragment>
|
||||
</qhelp>
|
||||
@@ -65,7 +65,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
* taken when this expression is true.
|
||||
*/
|
||||
ControlFlowNode getATrueSuccessor() {
|
||||
truecond_base(this, result) and
|
||||
qlCFGTrueSuccessor(this, result) and
|
||||
result = getASuccessor()
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
* taken when this expression is false.
|
||||
*/
|
||||
ControlFlowNode getAFalseSuccessor() {
|
||||
falsecond_base(this, result) and
|
||||
qlCFGFalseSuccessor(this, result) and
|
||||
result = getASuccessor()
|
||||
}
|
||||
|
||||
@@ -95,18 +95,20 @@ import ControlFlowGraphPublic
|
||||
class ControlFlowNodeBase extends ElementBase, @cfgnode { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ControlFlowNode.getATrueSuccessor()` instead.
|
||||
* Holds when `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
|
||||
*/
|
||||
predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
deprecated predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
qlCFGTrueSuccessor(n1, n2)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ControlFlowNode.getAFalseSuccessor()` instead.
|
||||
* Holds when `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
|
||||
*/
|
||||
predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
deprecated predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
qlCFGFalseSuccessor(n1, n2)
|
||||
}
|
||||
|
||||
@@ -134,7 +136,7 @@ abstract class AdditionalControlFlowEdge extends ControlFlowNodeBase {
|
||||
/**
|
||||
* Holds if there is a control-flow edge from `source` to `target` in either
|
||||
* the extractor-generated control-flow graph or in a subclass of
|
||||
* `AdditionalControlFlowEdge`. Use this relation instead of `successors`.
|
||||
* `AdditionalControlFlowEdge`. Use this relation instead of `qlCFGSuccessor`.
|
||||
*/
|
||||
predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) {
|
||||
qlCFGSuccessor(source, target)
|
||||
|
||||
@@ -1376,8 +1376,6 @@ private module Cached {
|
||||
/**
|
||||
* Holds if `n2` is a successor of `n1` in the CFG. This includes also
|
||||
* true-successors and false-successors.
|
||||
*
|
||||
* This corresponds to the old `successors` dbscheme relation.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGSuccessor(Node n1, Node n2) {
|
||||
@@ -1390,9 +1388,8 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n2` is a true-successor of `n1` in the CFG.
|
||||
*
|
||||
* This corresponds to the old `truecond` dbscheme relation.
|
||||
* Holds if `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGTrueSuccessor(Node n1, Node n2) {
|
||||
@@ -1401,9 +1398,8 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n2` is a false-successor of `n1` in the CFG.
|
||||
*
|
||||
* This corresponds to the old `falsecond` dbscheme relation.
|
||||
* Holds if `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGFalseSuccessor(Node n1, Node n2) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import cpp
|
||||
private import PrimitiveBasicBlocks
|
||||
private import semmle.code.cpp.controlflow.internal.CFG
|
||||
|
||||
private class Node = ControlFlowNodeBase;
|
||||
|
||||
@@ -153,8 +154,8 @@ private predicate nonAnalyzableFunction(Function f) {
|
||||
*/
|
||||
private predicate impossibleFalseEdge(Expr condition, Node succ) {
|
||||
conditionAlwaysTrue(condition) and
|
||||
falsecond_base(condition, succ) and
|
||||
not truecond_base(condition, succ)
|
||||
qlCFGFalseSuccessor(condition, succ) and
|
||||
not qlCFGTrueSuccessor(condition, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,8 +163,8 @@ private predicate impossibleFalseEdge(Expr condition, Node succ) {
|
||||
*/
|
||||
private predicate impossibleTrueEdge(Expr condition, Node succ) {
|
||||
conditionAlwaysFalse(condition) and
|
||||
truecond_base(condition, succ) and
|
||||
not falsecond_base(condition, succ)
|
||||
qlCFGTrueSuccessor(condition, succ) and
|
||||
not qlCFGFalseSuccessor(condition, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -863,9 +864,9 @@ library class ConditionEvaluator extends ExprEvaluator {
|
||||
ConditionEvaluator() { this = 0 }
|
||||
|
||||
override predicate interesting(Expr e) {
|
||||
falsecond_base(e, _)
|
||||
qlCFGFalseSuccessor(e, _)
|
||||
or
|
||||
truecond_base(e, _)
|
||||
qlCFGTrueSuccessor(e, _)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,13 +50,25 @@ class Node extends TNode {
|
||||
/** Gets the type of this node. */
|
||||
Type getType() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the expression corresponding to this node, if any. */
|
||||
/**
|
||||
* Gets the expression corresponding to this node, if any. This predicate
|
||||
* only has a result on nodes that represent the value of evaluating the
|
||||
* expression. For data flowing _out of_ an expression, like when an
|
||||
* argument is passed by reference, use `asDefiningArgument` instead of
|
||||
* `asExpr`.
|
||||
*/
|
||||
Expr asExpr() { result = this.(ExprNode).getExpr() }
|
||||
|
||||
/** Gets the parameter corresponding to this node, if any. */
|
||||
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
|
||||
|
||||
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
|
||||
/**
|
||||
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
|
||||
* This predicate should be used instead of `asExpr` when referring to the
|
||||
* value of a reference argument _after_ the call has returned. For example,
|
||||
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
|
||||
* that represents the new value of `x`.
|
||||
*/
|
||||
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
|
||||
|
||||
/**
|
||||
@@ -383,7 +395,9 @@ class PreConstructorInitThis extends Node, TPreConstructorInitThis {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Node` corresponding to `e`.
|
||||
* Gets the `Node` corresponding to the value of evaluating `e`. For data
|
||||
* flowing _out of_ an expression, like when an argument is passed by
|
||||
* reference, use `definitionByReferenceNodeFromArgument` instead.
|
||||
*/
|
||||
ExprNode exprNode(Expr e) { result.getExpr() = e }
|
||||
|
||||
|
||||
@@ -120,15 +120,25 @@ private module PartialDefinitions {
|
||||
)
|
||||
}
|
||||
|
||||
predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
|
||||
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
|
||||
|
||||
predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
|
||||
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
|
||||
|
||||
/**
|
||||
* Gets the subBasicBlock where this `PartialDefinition` is defined.
|
||||
*/
|
||||
ControlFlowNode getSubBasicBlockStart() { result = node }
|
||||
|
||||
/**
|
||||
* Holds if this `PartialDefinition` defines variable `v` at control-flow
|
||||
* node `cfn`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
|
||||
innerDefinedExpr = v.getAnAccess() and
|
||||
cfn = node
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this partial definition may modify `inner` (or what it points
|
||||
* to) through `outer`. These expressions will never be `Conversion`s.
|
||||
@@ -188,7 +198,7 @@ module FlowVar_internal {
|
||||
predicate fullySupportedSsaVariable(Variable v) {
|
||||
v = any(SsaDefinition def).getAVariable() and
|
||||
// A partially-defined variable is handled using the partial definitions logic.
|
||||
not any(PartialDefinition p).partiallyDefines(v) and
|
||||
not any(PartialDefinition p).partiallyDefinesVariableAt(v, _) and
|
||||
// SSA variables do not exist before their first assignment, but one
|
||||
// feature of this data flow library is to track where uninitialized data
|
||||
// ends up.
|
||||
@@ -232,7 +242,7 @@ module FlowVar_internal {
|
||||
or
|
||||
assignmentLikeOperation(sbb, v, _, _)
|
||||
or
|
||||
sbb = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
|
||||
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb))
|
||||
or
|
||||
blockVarDefinedByVariable(sbb, v)
|
||||
)
|
||||
@@ -363,8 +373,7 @@ module FlowVar_internal {
|
||||
|
||||
override predicate definedPartiallyAt(Expr e) {
|
||||
exists(PartialDefinition p |
|
||||
p.partiallyDefines(v) and
|
||||
sbb = p.getSubBasicBlockStart() and
|
||||
p.partiallyDefinesVariableAt(v, sbb) and
|
||||
p.definesExpressions(_, e)
|
||||
)
|
||||
}
|
||||
@@ -427,7 +436,7 @@ module FlowVar_internal {
|
||||
/**
|
||||
* Gets a variable that is assigned in this loop and read outside the loop.
|
||||
*/
|
||||
private Variable getARelevantVariable() {
|
||||
Variable getARelevantVariable() {
|
||||
result = this.getAVariableAssignedInLoop() and
|
||||
exists(VariableAccess va |
|
||||
va.getTarget() = result and
|
||||
@@ -472,10 +481,16 @@ module FlowVar_internal {
|
||||
reachesWithoutAssignment(bb.getAPredecessor(), v) and
|
||||
this.bbInLoop(bb)
|
||||
) and
|
||||
not assignmentLikeOperation(bb.getANode(), v, _, _)
|
||||
not assignsToVar(bb, v)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate assignsToVar(BasicBlock bb, Variable v) {
|
||||
assignmentLikeOperation(bb.getANode(), v, _, _) and
|
||||
exists(AlwaysTrueUponEntryLoop loop | v = loop.getARelevantVariable())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `loop` always assigns to `v` before leaving through an edge
|
||||
* from `bbInside` in its condition to `bbOutside` outside the loop. Also,
|
||||
@@ -736,7 +751,7 @@ module FlowVar_internal {
|
||||
exists(Variable v | not fullySupportedSsaVariable(v) |
|
||||
assignmentLikeOperation(this, v, _, _)
|
||||
or
|
||||
this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
|
||||
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this))
|
||||
// It is not necessary to cut the basic blocks at `Initializer` nodes
|
||||
// because the affected variable can have no _other_ value before its
|
||||
// initializer. It is not necessary to cut basic blocks at procedure
|
||||
|
||||
@@ -70,7 +70,7 @@ private DataFlow::Node getNodeForSource(Expr source) {
|
||||
//
|
||||
// This case goes together with the similar (but not identical) rule in
|
||||
// `nodeIsBarrierIn`.
|
||||
result = DataFlow::definitionByReferenceNode(source) and
|
||||
result = DataFlow::definitionByReferenceNodeFromArgument(source) and
|
||||
not argv(source.(VariableAccess).getTarget())
|
||||
)
|
||||
}
|
||||
@@ -210,7 +210,7 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) {
|
||||
or
|
||||
// This case goes together with the similar (but not identical) rule in
|
||||
// `getNodeForSource`.
|
||||
node = DataFlow::definitionByReferenceNode(source)
|
||||
node = DataFlow::definitionByReferenceNodeFromArgument(source)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -44,9 +44,14 @@ class Node extends TIRDataFlowNode {
|
||||
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
||||
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any. If
|
||||
* this node strictly (in the sense of `asConvertedExpr`) corresponds to a
|
||||
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
|
||||
* Gets the non-conversion expression corresponding to this node, if any.
|
||||
* This predicate only has a result on nodes that represent the value of
|
||||
* evaluating the expression. For data flowing _out of_ an expression, like
|
||||
* when an argument is passed by reference, use `asDefiningArgument` instead
|
||||
* of `asExpr`.
|
||||
*
|
||||
* If this node strictly (in the sense of `asConvertedExpr`) corresponds to
|
||||
* a `Conversion`, then the result is the underlying non-`Conversion` base
|
||||
* expression.
|
||||
*/
|
||||
Expr asExpr() { result = this.(ExprNode).getExpr() }
|
||||
@@ -57,7 +62,13 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() }
|
||||
|
||||
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
|
||||
/**
|
||||
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
|
||||
* This predicate should be used instead of `asExpr` when referring to the
|
||||
* value of a reference argument _after_ the call has returned. For example,
|
||||
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
|
||||
* that represents the new value of `x`.
|
||||
*/
|
||||
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
|
||||
|
||||
/** Gets the positional parameter corresponding to this node, if any. */
|
||||
@@ -392,7 +403,7 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
|
||||
class DefinitionByReferenceNode extends InstructionNode {
|
||||
override WriteSideEffectInstruction instr;
|
||||
|
||||
/** Gets the argument corresponding to this node. */
|
||||
/** Gets the unconverted argument corresponding to this node. */
|
||||
Expr getArgument() {
|
||||
result =
|
||||
instr
|
||||
@@ -476,20 +487,26 @@ class VariableNode extends Node, TVariableNode {
|
||||
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
|
||||
*
|
||||
* Gets the `Node` corresponding to a definition by reference of the variable
|
||||
* that is passed as `argument` of a call.
|
||||
*/
|
||||
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
|
||||
deprecated DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
|
||||
|
||||
/**
|
||||
* Gets a `Node` corresponding to `e` or any of its conversions. There is no
|
||||
* result if `e` is a `Conversion`.
|
||||
* Gets the `Node` corresponding to the value of evaluating `e` or any of its
|
||||
* conversions. There is no result if `e` is a `Conversion`. For data flowing
|
||||
* _out of_ an expression, like when an argument is passed by reference, use
|
||||
* `definitionByReferenceNodeFromArgument` instead.
|
||||
*/
|
||||
ExprNode exprNode(Expr e) { result.getExpr() = e }
|
||||
|
||||
/**
|
||||
* Gets the `Node` corresponding to `e`, if any. Here, `e` may be a
|
||||
* `Conversion`.
|
||||
* Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may
|
||||
* be a `Conversion`. For data flowing _out of_ an expression, like when an
|
||||
* argument is passed by reference, use
|
||||
* `definitionByReferenceNodeFromArgument` instead.
|
||||
*/
|
||||
ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
|
||||
|
||||
@@ -498,6 +515,14 @@ ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
|
||||
*/
|
||||
ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p }
|
||||
|
||||
/**
|
||||
* Gets the `Node` corresponding to a definition by reference of the variable
|
||||
* that is passed as unconverted `argument` of a call.
|
||||
*/
|
||||
DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
|
||||
result.getArgument() = argument
|
||||
}
|
||||
|
||||
/** Gets the `VariableNode` corresponding to the variable `v`. */
|
||||
VariableNode variableNode(Variable v) { result.getVariable() = v }
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.implementations.Iterator
|
||||
|
||||
/**
|
||||
* Additional model for standard container constructors that reference the
|
||||
@@ -26,9 +27,17 @@ class StdSequenceContainerConstructor extends Constructor, TaintFunction {
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
*/
|
||||
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// taint flow from any parameter of the value type to the returned object
|
||||
input.isParameterDeref(getAValueTypeParameterIndex()) and
|
||||
(
|
||||
input.isParameterDeref(getAValueTypeParameterIndex()) or
|
||||
input.isParameter(getAnIteratorParameterIndex())
|
||||
) and
|
||||
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
|
||||
}
|
||||
}
|
||||
@@ -88,6 +97,43 @@ class StdSequenceContainerFrontBack extends TaintFunction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard container functions `insert` and `insert_after`.
|
||||
*/
|
||||
class StdSequenceContainerInsert extends TaintFunction {
|
||||
StdSequenceContainerInsert() {
|
||||
this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or
|
||||
this.hasQualifiedName("std", ["forward_list"], "insert_after")
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is a reference to the
|
||||
* value type of the container.
|
||||
*/
|
||||
int getAValueTypeParameterIndex() {
|
||||
getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
*/
|
||||
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from parameter to container itself (qualifier) and return value
|
||||
(
|
||||
input.isQualifierObject() or
|
||||
input.isParameterDeref(getAValueTypeParameterIndex()) or
|
||||
input.isParameter(getAnIteratorParameterIndex())
|
||||
) and
|
||||
(
|
||||
output.isQualifierObject() or
|
||||
output.isReturnValueDeref()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard container function `assign`.
|
||||
*/
|
||||
@@ -105,13 +151,41 @@ class StdSequenceContainerAssign extends TaintFunction {
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
*/
|
||||
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from parameter to string itself (qualifier) and return value
|
||||
input.isParameterDeref(getAValueTypeParameterIndex()) and
|
||||
// flow from parameter to container itself (qualifier)
|
||||
(
|
||||
input.isParameterDeref(getAValueTypeParameterIndex()) or
|
||||
input.isParameter(getAnIteratorParameterIndex())
|
||||
) and
|
||||
output.isQualifierObject()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard container `begin` and `end` functions and their
|
||||
* variants.
|
||||
*/
|
||||
class StdSequenceContainerBeginEnd extends TaintFunction {
|
||||
StdSequenceContainerBeginEnd() {
|
||||
this
|
||||
.hasQualifiedName("std", ["array", "vector", "deque", "list"],
|
||||
["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) or
|
||||
this
|
||||
.hasQualifiedName("std", "forward_list",
|
||||
["before_begin", "begin", "end", "cbefore_begin", "cbegin", "cend"])
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isQualifierObject() and
|
||||
output.isReturnValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard container `swap` functions.
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,43 @@ class StdBasicString extends TemplateClass {
|
||||
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional model for `std::string` constructors that reference the character
|
||||
* type of the container, or an iterator. For example construction from
|
||||
* iterators:
|
||||
* ```
|
||||
* std::string b(a.begin(), a.end());
|
||||
* ```
|
||||
*/
|
||||
class StdStringConstructor extends Constructor, TaintFunction {
|
||||
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is a string (or
|
||||
* character).
|
||||
*/
|
||||
int getAStringParameterIndex() {
|
||||
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
|
||||
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
|
||||
getParameter(result).getUnspecifiedType() =
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
*/
|
||||
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// taint flow from any parameter of the value type to the returned object
|
||||
(
|
||||
input.isParameterDeref(getAStringParameterIndex()) or
|
||||
input.isParameter(getAnIteratorParameterIndex())
|
||||
) and
|
||||
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `std::string` function `c_str`.
|
||||
*/
|
||||
@@ -79,8 +116,8 @@ class StdStringAppend extends TaintFunction {
|
||||
* character).
|
||||
*/
|
||||
int getAStringParameterIndex() {
|
||||
getParameter(result).getType() instanceof PointerType or
|
||||
getParameter(result).getType() instanceof ReferenceType or
|
||||
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
|
||||
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
|
||||
getParameter(result).getUnspecifiedType() =
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
|
||||
}
|
||||
@@ -115,15 +152,23 @@ class StdStringAssign extends TaintFunction {
|
||||
* character).
|
||||
*/
|
||||
int getAStringParameterIndex() {
|
||||
getParameter(result).getType() instanceof PointerType or
|
||||
getParameter(result).getType() instanceof ReferenceType or
|
||||
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
|
||||
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
|
||||
getParameter(result).getUnspecifiedType() =
|
||||
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of a parameter to this function that is an iterator.
|
||||
*/
|
||||
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
// flow from parameter to string itself (qualifier) and return value
|
||||
input.isParameterDeref(getAStringParameterIndex()) and
|
||||
(
|
||||
input.isParameterDeref(getAStringParameterIndex()) or
|
||||
input.isParameter(getAnIteratorParameterIndex())
|
||||
) and
|
||||
(
|
||||
output.isQualifierObject() or
|
||||
output.isReturnValueDeref()
|
||||
@@ -137,14 +182,9 @@ class StdStringAssign extends TaintFunction {
|
||||
*/
|
||||
class StdStringBeginEnd extends TaintFunction {
|
||||
StdStringBeginEnd() {
|
||||
this.hasQualifiedName("std", "basic_string", "begin") or
|
||||
this.hasQualifiedName("std", "basic_string", "cbegin") or
|
||||
this.hasQualifiedName("std", "basic_string", "rbegin") or
|
||||
this.hasQualifiedName("std", "basic_string", "crbegin") or
|
||||
this.hasQualifiedName("std", "basic_string", "end") or
|
||||
this.hasQualifiedName("std", "basic_string", "cend") or
|
||||
this.hasQualifiedName("std", "basic_string", "rend") or
|
||||
this.hasQualifiedName("std", "basic_string", "crend")
|
||||
this
|
||||
.hasQualifiedName("std", "basic_string",
|
||||
["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"])
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
|
||||
@@ -319,28 +319,12 @@ private predicate defDependsOnDef(
|
||||
// Definitions with a defining value.
|
||||
exists(Expr expr | assignmentDef(def, v, expr) | exprDependsOnDef(expr, srcDef, srcVar))
|
||||
or
|
||||
exists(AssignAddExpr assignAdd |
|
||||
def = assignAdd and
|
||||
// Assignment operations with a defining value
|
||||
exists(AssignOperation assignOp |
|
||||
analyzableExpr(assignOp) and
|
||||
def = assignOp and
|
||||
def.getAVariable() = v and
|
||||
exprDependsOnDef(assignAdd.getAnOperand(), srcDef, srcVar)
|
||||
)
|
||||
or
|
||||
exists(AssignSubExpr assignSub |
|
||||
def = assignSub and
|
||||
def.getAVariable() = v and
|
||||
exprDependsOnDef(assignSub.getAnOperand(), srcDef, srcVar)
|
||||
)
|
||||
or
|
||||
exists(UnsignedAssignMulExpr assignMul |
|
||||
def = assignMul and
|
||||
def.getAVariable() = v and
|
||||
exprDependsOnDef(assignMul.getAnOperand(), srcDef, srcVar)
|
||||
)
|
||||
or
|
||||
exists(AssignMulByConstantExpr assignMul |
|
||||
def = assignMul and
|
||||
def.getAVariable() = v and
|
||||
exprDependsOnDef(assignMul.getLValue(), srcDef, srcVar)
|
||||
exprDependsOnDef(assignOp, srcDef, srcVar)
|
||||
)
|
||||
or
|
||||
exists(CrementOperation crem |
|
||||
@@ -1160,6 +1144,17 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
if guardLB > defLB then result = guardLB else result = defLB
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access, float neConstant, float lower |
|
||||
isNEPhi(v, phi, access, neConstant) and
|
||||
lower = getFullyConvertedLowerBounds(access) and
|
||||
if lower = neConstant then result = lower + 1 else result = lower
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access |
|
||||
isUnsupportedGuardPhi(v, phi, access) and
|
||||
result = getFullyConvertedLowerBounds(access)
|
||||
)
|
||||
or
|
||||
result = getDefLowerBounds(phi.getAPhiInput(v), v)
|
||||
}
|
||||
|
||||
@@ -1177,6 +1172,17 @@ private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
if guardUB < defUB then result = guardUB else result = defUB
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access, float neConstant, float upper |
|
||||
isNEPhi(v, phi, access, neConstant) and
|
||||
upper = getFullyConvertedUpperBounds(access) and
|
||||
if upper = neConstant then result = upper - 1 else result = upper
|
||||
)
|
||||
or
|
||||
exists(VariableAccess access |
|
||||
isUnsupportedGuardPhi(v, phi, access) and
|
||||
result = getFullyConvertedUpperBounds(access)
|
||||
)
|
||||
or
|
||||
result = getDefUpperBounds(phi.getAPhiInput(v), v)
|
||||
}
|
||||
|
||||
@@ -1185,42 +1191,11 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) {
|
||||
// Definitions with a defining value.
|
||||
exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedLowerBounds(expr))
|
||||
or
|
||||
exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsLB, float rhsLB |
|
||||
def = assignAdd and
|
||||
assignAdd.getLValue() = nextDef.getAUse(v) and
|
||||
lhsLB = getDefLowerBounds(nextDef, v) and
|
||||
rhsLB = getFullyConvertedLowerBounds(assignAdd.getRValue()) and
|
||||
result = addRoundingDown(lhsLB, rhsLB)
|
||||
)
|
||||
or
|
||||
exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsLB, float rhsUB |
|
||||
def = assignSub and
|
||||
assignSub.getLValue() = nextDef.getAUse(v) and
|
||||
lhsLB = getDefLowerBounds(nextDef, v) and
|
||||
rhsUB = getFullyConvertedUpperBounds(assignSub.getRValue()) and
|
||||
result = addRoundingDown(lhsLB, -rhsUB)
|
||||
)
|
||||
or
|
||||
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsLB, float rhsLB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsLB = getDefLowerBounds(nextDef, v) and
|
||||
rhsLB = getFullyConvertedLowerBounds(assignMul.getRValue()) and
|
||||
result = lhsLB * rhsLB
|
||||
)
|
||||
or
|
||||
exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsLB = getDefLowerBounds(nextDef, v) and
|
||||
result = lhsLB * assignMul.getConstant()
|
||||
)
|
||||
or
|
||||
exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsUB = getDefUpperBounds(nextDef, v) and
|
||||
result = lhsUB * assignMul.getConstant()
|
||||
// Assignment operations with a defining value
|
||||
exists(AssignOperation assignOp |
|
||||
def = assignOp and
|
||||
assignOp.getLValue() = v.getAnAccess() and
|
||||
result = getTruncatedLowerBounds(assignOp)
|
||||
)
|
||||
or
|
||||
exists(IncrementOperation incr, float newLB |
|
||||
@@ -1249,42 +1224,11 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) {
|
||||
// Definitions with a defining value.
|
||||
exists(Expr expr | assignmentDef(def, v, expr) | result = getFullyConvertedUpperBounds(expr))
|
||||
or
|
||||
exists(AssignAddExpr assignAdd, RangeSsaDefinition nextDef, float lhsUB, float rhsUB |
|
||||
def = assignAdd and
|
||||
assignAdd.getLValue() = nextDef.getAUse(v) and
|
||||
lhsUB = getDefUpperBounds(nextDef, v) and
|
||||
rhsUB = getFullyConvertedUpperBounds(assignAdd.getRValue()) and
|
||||
result = addRoundingUp(lhsUB, rhsUB)
|
||||
)
|
||||
or
|
||||
exists(AssignSubExpr assignSub, RangeSsaDefinition nextDef, float lhsUB, float rhsLB |
|
||||
def = assignSub and
|
||||
assignSub.getLValue() = nextDef.getAUse(v) and
|
||||
lhsUB = getDefUpperBounds(nextDef, v) and
|
||||
rhsLB = getFullyConvertedLowerBounds(assignSub.getRValue()) and
|
||||
result = addRoundingUp(lhsUB, -rhsLB)
|
||||
)
|
||||
or
|
||||
exists(UnsignedAssignMulExpr assignMul, RangeSsaDefinition nextDef, float lhsUB, float rhsUB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsUB = getDefUpperBounds(nextDef, v) and
|
||||
rhsUB = getFullyConvertedUpperBounds(assignMul.getRValue()) and
|
||||
result = lhsUB * rhsUB
|
||||
)
|
||||
or
|
||||
exists(AssignMulByPositiveConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsUB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsUB = getDefUpperBounds(nextDef, v) and
|
||||
result = lhsUB * assignMul.getConstant()
|
||||
)
|
||||
or
|
||||
exists(AssignMulByNegativeConstantExpr assignMul, RangeSsaDefinition nextDef, float lhsLB |
|
||||
def = assignMul and
|
||||
assignMul.getLValue() = nextDef.getAUse(v) and
|
||||
lhsLB = getDefLowerBounds(nextDef, v) and
|
||||
result = lhsLB * assignMul.getConstant()
|
||||
// Assignment operations with a defining value
|
||||
exists(AssignOperation assignOp |
|
||||
def = assignOp and
|
||||
assignOp.getLValue() = v.getAnAccess() and
|
||||
result = getTruncatedUpperBounds(assignOp)
|
||||
)
|
||||
or
|
||||
exists(IncrementOperation incr, float newUB |
|
||||
@@ -1501,22 +1445,13 @@ private predicate linearBoundFromGuard(
|
||||
// 1. x <= upperbound(RHS)
|
||||
// 2. x >= lowerbound(RHS)
|
||||
//
|
||||
// For x != RHS, we create trivial bounds:
|
||||
//
|
||||
// 1. x <= typeUpperBound(RHS.getUnspecifiedType())
|
||||
// 2. x >= typeLowerBound(RHS.getUnspecifiedType())
|
||||
//
|
||||
exists(Expr lhs, Expr rhs, boolean isEQ |
|
||||
exists(Expr lhs, Expr rhs |
|
||||
linearAccess(lhs, v, p, q) and
|
||||
eqOpWithSwapAndNegate(guard, lhs, rhs, isEQ, branch) and
|
||||
eqOpWithSwapAndNegate(guard, lhs, rhs, true, branch) and
|
||||
getBounds(rhs, boundValue, isLowerBound) and
|
||||
strictness = Nonstrict()
|
||||
|
|
||||
// True branch
|
||||
isEQ = true and getBounds(rhs, boundValue, isLowerBound)
|
||||
or
|
||||
// False branch: set the bounds to the min/max for the type.
|
||||
isEQ = false and exprTypeBounds(rhs, boundValue, isLowerBound)
|
||||
)
|
||||
// x != RHS and !x are handled elsewhere
|
||||
}
|
||||
|
||||
/** Utility for `linearBoundFromGuard`. */
|
||||
@@ -1533,6 +1468,42 @@ private predicate exprTypeBounds(Expr expr, float boundValue, boolean isLowerBou
|
||||
isLowerBound = false and boundValue = exprMaxVal(expr.getFullyConverted())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(v, phi)` ensures that `access` is not equal to `neConstant`. For
|
||||
* example, the condition `if (x + 1 != 3)` ensures that `x` is not equal to 2.
|
||||
* Only integral types are supported.
|
||||
*/
|
||||
private predicate isNEPhi(
|
||||
Variable v, RangeSsaDefinition phi, VariableAccess access, float neConstant
|
||||
) {
|
||||
exists(
|
||||
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
|
||||
r = getValue(rExpr).toFloat() and
|
||||
linearAccess(linearExpr, access, p, q) and
|
||||
neConstant = (r - q) / p
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(v, phi)` constrains the value of `access` but in a way that
|
||||
* doesn't allow this library to constrain the upper or lower bounds of
|
||||
* `access`. An example is `if (x != y)` if neither `x` nor `y` is a
|
||||
* compile-time constant.
|
||||
*/
|
||||
private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, VariableAccess access) {
|
||||
exists(ComparisonOperation cmp, boolean branch |
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
eqOpWithSwapAndNegate(cmp, _, _, false, branch) and
|
||||
not isNEPhi(v, phi, access, _)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module SimpleRangeAnalysisCached {
|
||||
/**
|
||||
|
||||
@@ -1935,20 +1935,6 @@ stmtparents(
|
||||
ishandler(unique int block: @stmt_block ref);
|
||||
|
||||
@cfgnode = @stmt | @expr | @function | @initialiser ;
|
||||
successors(
|
||||
int from: @cfgnode ref,
|
||||
int to: @cfgnode ref
|
||||
);
|
||||
|
||||
truecond(
|
||||
unique int from: @cfgnode ref,
|
||||
int to: @cfgnode ref
|
||||
);
|
||||
|
||||
falsecond(
|
||||
unique int from: @cfgnode ref,
|
||||
int to: @cfgnode ref
|
||||
);
|
||||
|
||||
stmt_decl_bind(
|
||||
int stmt: @stmt_decl ref,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -245,6 +245,8 @@
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||
| file://:0:0:0:0 | p#0 | file://:0:0:0:0 | p#0 | |
|
||||
| format.cpp:16:21:16:21 | s | format.cpp:22:22:22:22 | s | |
|
||||
| format.cpp:16:31:16:31 | n | format.cpp:22:25:22:25 | n | |
|
||||
| format.cpp:16:46:16:51 | format | format.cpp:22:28:22:33 | format | |
|
||||
@@ -459,12 +461,12 @@
|
||||
| standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:53:12:53:18 | source1 | |
|
||||
| standalone_iterators.cpp:51:37:51:43 | source1 | standalone_iterators.cpp:54:14:54:20 | source1 | |
|
||||
| standalone_iterators.cpp:53:12:53:18 | ref arg source1 | standalone_iterators.cpp:54:14:54:20 | source1 | |
|
||||
| stl.h:156:30:156:40 | call to allocator | stl.h:156:21:156:41 | noexcept(...) | TAINT |
|
||||
| stl.h:156:30:156:40 | call to allocator | stl.h:156:21:156:41 | noexcept(...) | TAINT |
|
||||
| stl.h:156:30:156:40 | call to allocator | stl.h:156:21:156:41 | noexcept(...) | TAINT |
|
||||
| stl.h:156:30:156:40 | call to allocator | stl.h:156:21:156:41 | noexcept(...) | TAINT |
|
||||
| stl.h:156:30:156:40 | call to allocator | stl.h:156:21:156:41 | noexcept(...) | TAINT |
|
||||
| stl.h:156:53:156:63 | 0 | stl.h:156:46:156:64 | (no string representation) | TAINT |
|
||||
| stl.h:172:30:172:40 | call to allocator | stl.h:172:21:172:41 | noexcept(...) | TAINT |
|
||||
| stl.h:172:30:172:40 | call to allocator | stl.h:172:21:172:41 | noexcept(...) | TAINT |
|
||||
| stl.h:172:30:172:40 | call to allocator | stl.h:172:21:172:41 | noexcept(...) | TAINT |
|
||||
| stl.h:172:30:172:40 | call to allocator | stl.h:172:21:172:41 | noexcept(...) | TAINT |
|
||||
| stl.h:172:30:172:40 | call to allocator | stl.h:172:21:172:41 | noexcept(...) | TAINT |
|
||||
| stl.h:172:53:172:63 | 0 | stl.h:172:46:172:64 | (no string representation) | TAINT |
|
||||
| string.cpp:24:12:24:17 | call to source | string.cpp:28:7:28:7 | a | |
|
||||
| string.cpp:25:16:25:20 | 123 | string.cpp:25:16:25:21 | call to basic_string | TAINT |
|
||||
| string.cpp:25:16:25:21 | call to basic_string | string.cpp:29:7:29:7 | b | |
|
||||
@@ -527,6 +529,7 @@
|
||||
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | |
|
||||
| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator* | TAINT |
|
||||
| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator++ | TAINT |
|
||||
| string.cpp:120:15:120:15 | (__end) | string.cpp:120:15:120:15 | call to iterator | |
|
||||
| string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to begin | TAINT |
|
||||
| string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to end | TAINT |
|
||||
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
|
||||
@@ -557,6 +560,7 @@
|
||||
| string.cpp:125:9:125:10 | it | string.cpp:125:8:125:8 | call to operator* | TAINT |
|
||||
| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator* | TAINT |
|
||||
| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator++ | TAINT |
|
||||
| string.cpp:128:16:128:16 | (__end) | string.cpp:128:16:128:16 | call to iterator | |
|
||||
| string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to begin | TAINT |
|
||||
| string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to end | TAINT |
|
||||
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
|
||||
@@ -1011,6 +1015,228 @@
|
||||
| string.cpp:412:5:412:6 | i9 | string.cpp:412:3:412:3 | call to operator-- | TAINT |
|
||||
| string.cpp:412:5:412:6 | ref arg i9 | string.cpp:413:9:413:10 | i9 | |
|
||||
| string.cpp:413:9:413:10 | i9 | string.cpp:413:8:413:8 | call to operator* | TAINT |
|
||||
| string.cpp:419:17:419:20 | aa | string.cpp:419:17:419:21 | call to basic_string | TAINT |
|
||||
| string.cpp:419:17:419:21 | call to basic_string | string.cpp:424:7:424:8 | s1 | |
|
||||
| string.cpp:419:17:419:21 | call to basic_string | string.cpp:425:7:425:8 | s1 | |
|
||||
| string.cpp:420:17:420:20 | bb | string.cpp:420:17:420:21 | call to basic_string | TAINT |
|
||||
| string.cpp:420:17:420:21 | call to basic_string | string.cpp:427:7:427:8 | s2 | |
|
||||
| string.cpp:420:17:420:21 | call to basic_string | string.cpp:428:7:428:8 | s2 | |
|
||||
| string.cpp:421:14:421:17 | cc | string.cpp:424:20:424:22 | cs1 | |
|
||||
| string.cpp:422:14:422:19 | call to source | string.cpp:427:20:427:22 | cs2 | |
|
||||
| string.cpp:424:7:424:8 | ref arg s1 | string.cpp:425:7:425:8 | s1 | |
|
||||
| string.cpp:424:7:424:8 | s1 | string.cpp:424:10:424:15 | call to insert | TAINT |
|
||||
| string.cpp:424:20:424:22 | cs1 | string.cpp:424:7:424:8 | ref arg s1 | TAINT |
|
||||
| string.cpp:424:20:424:22 | cs1 | string.cpp:424:10:424:15 | call to insert | TAINT |
|
||||
| string.cpp:427:7:427:8 | ref arg s2 | string.cpp:428:7:428:8 | s2 | |
|
||||
| string.cpp:427:7:427:8 | s2 | string.cpp:427:10:427:15 | call to insert | TAINT |
|
||||
| string.cpp:427:20:427:22 | cs2 | string.cpp:427:7:427:8 | ref arg s2 | TAINT |
|
||||
| string.cpp:427:20:427:22 | cs2 | string.cpp:427:10:427:15 | call to insert | TAINT |
|
||||
| string.cpp:436:17:436:20 | aa | string.cpp:436:17:436:21 | call to basic_string | TAINT |
|
||||
| string.cpp:436:17:436:21 | call to basic_string | string.cpp:439:8:439:8 | a | |
|
||||
| string.cpp:436:17:436:21 | call to basic_string | string.cpp:439:17:439:17 | a | |
|
||||
| string.cpp:436:17:436:21 | call to basic_string | string.cpp:440:8:440:8 | a | |
|
||||
| string.cpp:437:17:437:20 | bb | string.cpp:437:17:437:21 | call to basic_string | TAINT |
|
||||
| string.cpp:437:17:437:21 | call to basic_string | string.cpp:442:8:442:8 | b | |
|
||||
| string.cpp:437:17:437:21 | call to basic_string | string.cpp:442:17:442:17 | b | |
|
||||
| string.cpp:437:17:437:21 | call to basic_string | string.cpp:443:8:443:8 | b | |
|
||||
| string.cpp:439:8:439:8 | a | string.cpp:439:10:439:15 | call to insert | TAINT |
|
||||
| string.cpp:439:8:439:8 | ref arg a | string.cpp:440:8:440:8 | a | |
|
||||
| string.cpp:439:17:439:17 | a | string.cpp:439:19:439:23 | call to begin | TAINT |
|
||||
| string.cpp:439:17:439:17 | ref arg a | string.cpp:439:8:439:8 | a | |
|
||||
| string.cpp:439:17:439:17 | ref arg a | string.cpp:440:8:440:8 | a | |
|
||||
| string.cpp:439:19:439:23 | call to begin | string.cpp:439:17:439:25 | call to iterator | TAINT |
|
||||
| string.cpp:439:32:439:34 | 120 | string.cpp:439:8:439:8 | ref arg a | TAINT |
|
||||
| string.cpp:439:32:439:34 | 120 | string.cpp:439:10:439:15 | call to insert | TAINT |
|
||||
| string.cpp:442:8:442:8 | b | string.cpp:442:10:442:15 | call to insert | TAINT |
|
||||
| string.cpp:442:8:442:8 | ref arg b | string.cpp:443:8:443:8 | b | |
|
||||
| string.cpp:442:17:442:17 | b | string.cpp:442:19:442:23 | call to begin | TAINT |
|
||||
| string.cpp:442:17:442:17 | ref arg b | string.cpp:442:8:442:8 | b | |
|
||||
| string.cpp:442:17:442:17 | ref arg b | string.cpp:443:8:443:8 | b | |
|
||||
| string.cpp:442:19:442:23 | call to begin | string.cpp:442:17:442:25 | call to iterator | TAINT |
|
||||
| string.cpp:442:32:442:46 | call to source | string.cpp:442:8:442:8 | ref arg b | TAINT |
|
||||
| string.cpp:442:32:442:46 | call to source | string.cpp:442:10:442:15 | call to insert | TAINT |
|
||||
| string.cpp:447:17:447:20 | cc | string.cpp:447:17:447:21 | call to basic_string | TAINT |
|
||||
| string.cpp:447:17:447:21 | call to basic_string | string.cpp:452:8:452:8 | c | |
|
||||
| string.cpp:447:17:447:21 | call to basic_string | string.cpp:452:17:452:17 | c | |
|
||||
| string.cpp:447:17:447:21 | call to basic_string | string.cpp:453:8:453:8 | c | |
|
||||
| string.cpp:448:17:448:20 | dd | string.cpp:448:17:448:21 | call to basic_string | TAINT |
|
||||
| string.cpp:448:17:448:21 | call to basic_string | string.cpp:455:8:455:8 | d | |
|
||||
| string.cpp:448:17:448:21 | call to basic_string | string.cpp:455:17:455:17 | d | |
|
||||
| string.cpp:448:17:448:21 | call to basic_string | string.cpp:456:8:456:8 | d | |
|
||||
| string.cpp:449:18:449:21 | 11 | string.cpp:449:18:449:22 | call to basic_string | TAINT |
|
||||
| string.cpp:449:18:449:22 | call to basic_string | string.cpp:452:26:452:27 | s1 | |
|
||||
| string.cpp:449:18:449:22 | call to basic_string | string.cpp:452:38:452:39 | s1 | |
|
||||
| string.cpp:449:18:449:22 | call to basic_string | string.cpp:458:28:458:29 | s1 | |
|
||||
| string.cpp:449:18:449:22 | call to basic_string | string.cpp:458:40:458:41 | s1 | |
|
||||
| string.cpp:450:18:450:23 | call to source | string.cpp:450:18:450:26 | call to basic_string | TAINT |
|
||||
| string.cpp:450:18:450:26 | call to basic_string | string.cpp:455:26:455:27 | s2 | |
|
||||
| string.cpp:450:18:450:26 | call to basic_string | string.cpp:455:38:455:39 | s2 | |
|
||||
| string.cpp:450:18:450:26 | call to basic_string | string.cpp:458:8:458:9 | s2 | |
|
||||
| string.cpp:450:18:450:26 | call to basic_string | string.cpp:458:18:458:19 | s2 | |
|
||||
| string.cpp:450:18:450:26 | call to basic_string | string.cpp:459:8:459:9 | s2 | |
|
||||
| string.cpp:452:8:452:8 | c | string.cpp:452:10:452:15 | call to insert | TAINT |
|
||||
| string.cpp:452:8:452:8 | ref arg c | string.cpp:453:8:453:8 | c | |
|
||||
| string.cpp:452:17:452:17 | c | string.cpp:452:19:452:21 | call to end | TAINT |
|
||||
| string.cpp:452:17:452:17 | ref arg c | string.cpp:452:8:452:8 | c | |
|
||||
| string.cpp:452:17:452:17 | ref arg c | string.cpp:453:8:453:8 | c | |
|
||||
| string.cpp:452:19:452:21 | call to end | string.cpp:452:17:452:23 | call to iterator | TAINT |
|
||||
| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:452:38:452:39 | s1 | |
|
||||
| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:458:28:458:29 | s1 | |
|
||||
| string.cpp:452:26:452:27 | ref arg s1 | string.cpp:458:40:458:41 | s1 | |
|
||||
| string.cpp:452:26:452:27 | s1 | string.cpp:452:29:452:33 | call to begin | TAINT |
|
||||
| string.cpp:452:29:452:33 | call to begin | string.cpp:452:8:452:8 | ref arg c | TAINT |
|
||||
| string.cpp:452:29:452:33 | call to begin | string.cpp:452:10:452:15 | call to insert | TAINT |
|
||||
| string.cpp:452:38:452:39 | ref arg s1 | string.cpp:458:28:458:29 | s1 | |
|
||||
| string.cpp:452:38:452:39 | ref arg s1 | string.cpp:458:40:458:41 | s1 | |
|
||||
| string.cpp:452:38:452:39 | s1 | string.cpp:452:41:452:43 | call to end | TAINT |
|
||||
| string.cpp:452:41:452:43 | call to end | string.cpp:452:8:452:8 | ref arg c | TAINT |
|
||||
| string.cpp:452:41:452:43 | call to end | string.cpp:452:10:452:15 | call to insert | TAINT |
|
||||
| string.cpp:455:8:455:8 | d | string.cpp:455:10:455:15 | call to insert | TAINT |
|
||||
| string.cpp:455:8:455:8 | ref arg d | string.cpp:456:8:456:8 | d | |
|
||||
| string.cpp:455:17:455:17 | d | string.cpp:455:19:455:21 | call to end | TAINT |
|
||||
| string.cpp:455:17:455:17 | ref arg d | string.cpp:455:8:455:8 | d | |
|
||||
| string.cpp:455:17:455:17 | ref arg d | string.cpp:456:8:456:8 | d | |
|
||||
| string.cpp:455:19:455:21 | call to end | string.cpp:455:17:455:23 | call to iterator | TAINT |
|
||||
| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:455:38:455:39 | s2 | |
|
||||
| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:458:8:458:9 | s2 | |
|
||||
| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:458:18:458:19 | s2 | |
|
||||
| string.cpp:455:26:455:27 | ref arg s2 | string.cpp:459:8:459:9 | s2 | |
|
||||
| string.cpp:455:26:455:27 | s2 | string.cpp:455:29:455:33 | call to begin | TAINT |
|
||||
| string.cpp:455:29:455:33 | call to begin | string.cpp:455:8:455:8 | ref arg d | TAINT |
|
||||
| string.cpp:455:29:455:33 | call to begin | string.cpp:455:10:455:15 | call to insert | TAINT |
|
||||
| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:458:8:458:9 | s2 | |
|
||||
| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:458:18:458:19 | s2 | |
|
||||
| string.cpp:455:38:455:39 | ref arg s2 | string.cpp:459:8:459:9 | s2 | |
|
||||
| string.cpp:455:38:455:39 | s2 | string.cpp:455:41:455:43 | call to end | TAINT |
|
||||
| string.cpp:455:41:455:43 | call to end | string.cpp:455:8:455:8 | ref arg d | TAINT |
|
||||
| string.cpp:455:41:455:43 | call to end | string.cpp:455:10:455:15 | call to insert | TAINT |
|
||||
| string.cpp:458:8:458:9 | ref arg s2 | string.cpp:459:8:459:9 | s2 | |
|
||||
| string.cpp:458:8:458:9 | s2 | string.cpp:458:11:458:16 | call to insert | TAINT |
|
||||
| string.cpp:458:18:458:19 | ref arg s2 | string.cpp:458:8:458:9 | s2 | |
|
||||
| string.cpp:458:18:458:19 | ref arg s2 | string.cpp:459:8:459:9 | s2 | |
|
||||
| string.cpp:458:18:458:19 | s2 | string.cpp:458:21:458:23 | call to end | TAINT |
|
||||
| string.cpp:458:21:458:23 | call to end | string.cpp:458:18:458:25 | call to iterator | TAINT |
|
||||
| string.cpp:458:28:458:29 | ref arg s1 | string.cpp:458:40:458:41 | s1 | |
|
||||
| string.cpp:458:28:458:29 | s1 | string.cpp:458:31:458:35 | call to begin | TAINT |
|
||||
| string.cpp:458:31:458:35 | call to begin | string.cpp:458:8:458:9 | ref arg s2 | TAINT |
|
||||
| string.cpp:458:31:458:35 | call to begin | string.cpp:458:11:458:16 | call to insert | TAINT |
|
||||
| string.cpp:458:40:458:41 | s1 | string.cpp:458:43:458:45 | call to end | TAINT |
|
||||
| string.cpp:458:43:458:45 | call to end | string.cpp:458:8:458:9 | ref arg s2 | TAINT |
|
||||
| string.cpp:458:43:458:45 | call to end | string.cpp:458:11:458:16 | call to insert | TAINT |
|
||||
| string.cpp:463:17:463:20 | ee | string.cpp:463:17:463:21 | call to basic_string | TAINT |
|
||||
| string.cpp:463:17:463:21 | call to basic_string | string.cpp:468:8:468:8 | e | |
|
||||
| string.cpp:463:17:463:21 | call to basic_string | string.cpp:469:8:469:8 | e | |
|
||||
| string.cpp:464:17:464:20 | ff | string.cpp:464:17:464:21 | call to basic_string | TAINT |
|
||||
| string.cpp:464:17:464:21 | call to basic_string | string.cpp:471:8:471:8 | f | |
|
||||
| string.cpp:464:17:464:21 | call to basic_string | string.cpp:472:8:472:8 | f | |
|
||||
| string.cpp:465:18:465:21 | 33 | string.cpp:465:18:465:22 | call to basic_string | TAINT |
|
||||
| string.cpp:465:18:465:22 | call to basic_string | string.cpp:468:17:468:18 | s3 | |
|
||||
| string.cpp:465:18:465:22 | call to basic_string | string.cpp:468:29:468:30 | s3 | |
|
||||
| string.cpp:465:18:465:22 | call to basic_string | string.cpp:474:18:474:19 | s3 | |
|
||||
| string.cpp:465:18:465:22 | call to basic_string | string.cpp:474:30:474:31 | s3 | |
|
||||
| string.cpp:466:18:466:23 | call to source | string.cpp:466:18:466:26 | call to basic_string | TAINT |
|
||||
| string.cpp:466:18:466:26 | call to basic_string | string.cpp:471:17:471:18 | s4 | |
|
||||
| string.cpp:466:18:466:26 | call to basic_string | string.cpp:471:29:471:30 | s4 | |
|
||||
| string.cpp:466:18:466:26 | call to basic_string | string.cpp:474:8:474:9 | s4 | |
|
||||
| string.cpp:466:18:466:26 | call to basic_string | string.cpp:475:8:475:9 | s4 | |
|
||||
| string.cpp:468:8:468:8 | e | string.cpp:468:10:468:15 | call to append | TAINT |
|
||||
| string.cpp:468:8:468:8 | ref arg e | string.cpp:469:8:469:8 | e | |
|
||||
| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:468:29:468:30 | s3 | |
|
||||
| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:474:18:474:19 | s3 | |
|
||||
| string.cpp:468:17:468:18 | ref arg s3 | string.cpp:474:30:474:31 | s3 | |
|
||||
| string.cpp:468:17:468:18 | s3 | string.cpp:468:20:468:24 | call to begin | TAINT |
|
||||
| string.cpp:468:20:468:24 | call to begin | string.cpp:468:8:468:8 | ref arg e | TAINT |
|
||||
| string.cpp:468:20:468:24 | call to begin | string.cpp:468:10:468:15 | call to append | TAINT |
|
||||
| string.cpp:468:29:468:30 | ref arg s3 | string.cpp:474:18:474:19 | s3 | |
|
||||
| string.cpp:468:29:468:30 | ref arg s3 | string.cpp:474:30:474:31 | s3 | |
|
||||
| string.cpp:468:29:468:30 | s3 | string.cpp:468:32:468:34 | call to end | TAINT |
|
||||
| string.cpp:468:32:468:34 | call to end | string.cpp:468:8:468:8 | ref arg e | TAINT |
|
||||
| string.cpp:468:32:468:34 | call to end | string.cpp:468:10:468:15 | call to append | TAINT |
|
||||
| string.cpp:471:8:471:8 | f | string.cpp:471:10:471:15 | call to append | TAINT |
|
||||
| string.cpp:471:8:471:8 | ref arg f | string.cpp:472:8:472:8 | f | |
|
||||
| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:471:29:471:30 | s4 | |
|
||||
| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:474:8:474:9 | s4 | |
|
||||
| string.cpp:471:17:471:18 | ref arg s4 | string.cpp:475:8:475:9 | s4 | |
|
||||
| string.cpp:471:17:471:18 | s4 | string.cpp:471:20:471:24 | call to begin | TAINT |
|
||||
| string.cpp:471:20:471:24 | call to begin | string.cpp:471:8:471:8 | ref arg f | TAINT |
|
||||
| string.cpp:471:20:471:24 | call to begin | string.cpp:471:10:471:15 | call to append | TAINT |
|
||||
| string.cpp:471:29:471:30 | ref arg s4 | string.cpp:474:8:474:9 | s4 | |
|
||||
| string.cpp:471:29:471:30 | ref arg s4 | string.cpp:475:8:475:9 | s4 | |
|
||||
| string.cpp:471:29:471:30 | s4 | string.cpp:471:32:471:34 | call to end | TAINT |
|
||||
| string.cpp:471:32:471:34 | call to end | string.cpp:471:8:471:8 | ref arg f | TAINT |
|
||||
| string.cpp:471:32:471:34 | call to end | string.cpp:471:10:471:15 | call to append | TAINT |
|
||||
| string.cpp:474:8:474:9 | ref arg s4 | string.cpp:475:8:475:9 | s4 | |
|
||||
| string.cpp:474:8:474:9 | s4 | string.cpp:474:11:474:16 | call to append | TAINT |
|
||||
| string.cpp:474:18:474:19 | ref arg s3 | string.cpp:474:30:474:31 | s3 | |
|
||||
| string.cpp:474:18:474:19 | s3 | string.cpp:474:21:474:25 | call to begin | TAINT |
|
||||
| string.cpp:474:21:474:25 | call to begin | string.cpp:474:8:474:9 | ref arg s4 | TAINT |
|
||||
| string.cpp:474:21:474:25 | call to begin | string.cpp:474:11:474:16 | call to append | TAINT |
|
||||
| string.cpp:474:30:474:31 | s3 | string.cpp:474:33:474:35 | call to end | TAINT |
|
||||
| string.cpp:474:33:474:35 | call to end | string.cpp:474:8:474:9 | ref arg s4 | TAINT |
|
||||
| string.cpp:474:33:474:35 | call to end | string.cpp:474:11:474:16 | call to append | TAINT |
|
||||
| string.cpp:479:17:479:20 | gg | string.cpp:479:17:479:21 | call to basic_string | TAINT |
|
||||
| string.cpp:479:17:479:21 | call to basic_string | string.cpp:484:8:484:8 | g | |
|
||||
| string.cpp:479:17:479:21 | call to basic_string | string.cpp:485:8:485:8 | g | |
|
||||
| string.cpp:480:17:480:20 | hh | string.cpp:480:17:480:21 | call to basic_string | TAINT |
|
||||
| string.cpp:480:17:480:21 | call to basic_string | string.cpp:487:8:487:8 | h | |
|
||||
| string.cpp:480:17:480:21 | call to basic_string | string.cpp:488:8:488:8 | h | |
|
||||
| string.cpp:481:18:481:21 | 55 | string.cpp:481:18:481:22 | call to basic_string | TAINT |
|
||||
| string.cpp:481:18:481:22 | call to basic_string | string.cpp:484:17:484:18 | s5 | |
|
||||
| string.cpp:481:18:481:22 | call to basic_string | string.cpp:484:30:484:31 | s5 | |
|
||||
| string.cpp:481:18:481:22 | call to basic_string | string.cpp:490:18:490:19 | s5 | |
|
||||
| string.cpp:481:18:481:22 | call to basic_string | string.cpp:490:31:490:32 | s5 | |
|
||||
| string.cpp:482:18:482:23 | call to source | string.cpp:482:18:482:26 | call to basic_string | TAINT |
|
||||
| string.cpp:482:18:482:26 | call to basic_string | string.cpp:487:17:487:18 | s6 | |
|
||||
| string.cpp:482:18:482:26 | call to basic_string | string.cpp:487:30:487:31 | s6 | |
|
||||
| string.cpp:482:18:482:26 | call to basic_string | string.cpp:490:8:490:9 | s6 | |
|
||||
| string.cpp:482:18:482:26 | call to basic_string | string.cpp:491:8:491:9 | s6 | |
|
||||
| string.cpp:484:8:484:8 | ref arg g | string.cpp:485:8:485:8 | g | |
|
||||
| string.cpp:484:17:484:18 | s5 | string.cpp:484:20:484:25 | call to cbegin | TAINT |
|
||||
| string.cpp:484:20:484:25 | call to cbegin | string.cpp:484:8:484:8 | ref arg g | TAINT |
|
||||
| string.cpp:484:20:484:25 | call to cbegin | string.cpp:484:10:484:15 | call to assign | TAINT |
|
||||
| string.cpp:484:30:484:31 | s5 | string.cpp:484:33:484:36 | call to cend | TAINT |
|
||||
| string.cpp:484:33:484:36 | call to cend | string.cpp:484:8:484:8 | ref arg g | TAINT |
|
||||
| string.cpp:484:33:484:36 | call to cend | string.cpp:484:10:484:15 | call to assign | TAINT |
|
||||
| string.cpp:487:8:487:8 | ref arg h | string.cpp:488:8:488:8 | h | |
|
||||
| string.cpp:487:17:487:18 | s6 | string.cpp:487:20:487:25 | call to cbegin | TAINT |
|
||||
| string.cpp:487:20:487:25 | call to cbegin | string.cpp:487:8:487:8 | ref arg h | TAINT |
|
||||
| string.cpp:487:20:487:25 | call to cbegin | string.cpp:487:10:487:15 | call to assign | TAINT |
|
||||
| string.cpp:487:30:487:31 | s6 | string.cpp:487:33:487:36 | call to cend | TAINT |
|
||||
| string.cpp:487:33:487:36 | call to cend | string.cpp:487:8:487:8 | ref arg h | TAINT |
|
||||
| string.cpp:487:33:487:36 | call to cend | string.cpp:487:10:487:15 | call to assign | TAINT |
|
||||
| string.cpp:490:8:490:9 | ref arg s6 | string.cpp:491:8:491:9 | s6 | |
|
||||
| string.cpp:490:18:490:19 | s5 | string.cpp:490:21:490:26 | call to cbegin | TAINT |
|
||||
| string.cpp:490:21:490:26 | call to cbegin | string.cpp:490:8:490:9 | ref arg s6 | TAINT |
|
||||
| string.cpp:490:21:490:26 | call to cbegin | string.cpp:490:11:490:16 | call to assign | TAINT |
|
||||
| string.cpp:490:31:490:32 | s5 | string.cpp:490:34:490:37 | call to cend | TAINT |
|
||||
| string.cpp:490:34:490:37 | call to cend | string.cpp:490:8:490:9 | ref arg s6 | TAINT |
|
||||
| string.cpp:490:34:490:37 | call to cend | string.cpp:490:11:490:16 | call to assign | TAINT |
|
||||
| string.cpp:496:14:496:18 | abc | string.cpp:498:17:498:19 | cs1 | |
|
||||
| string.cpp:497:14:497:19 | call to source | string.cpp:499:17:499:19 | cs2 | |
|
||||
| string.cpp:498:17:498:19 | cs1 | string.cpp:498:17:498:20 | call to basic_string | TAINT |
|
||||
| string.cpp:498:17:498:20 | call to basic_string | string.cpp:500:17:500:18 | s1 | |
|
||||
| string.cpp:498:17:498:20 | call to basic_string | string.cpp:500:29:500:30 | s1 | |
|
||||
| string.cpp:498:17:498:20 | call to basic_string | string.cpp:503:7:503:8 | s1 | |
|
||||
| string.cpp:499:17:499:19 | cs2 | string.cpp:499:17:499:20 | call to basic_string | TAINT |
|
||||
| string.cpp:499:17:499:20 | call to basic_string | string.cpp:501:17:501:18 | s2 | |
|
||||
| string.cpp:499:17:499:20 | call to basic_string | string.cpp:501:29:501:30 | s2 | |
|
||||
| string.cpp:499:17:499:20 | call to basic_string | string.cpp:504:7:504:8 | s2 | |
|
||||
| string.cpp:500:17:500:18 | ref arg s1 | string.cpp:500:29:500:30 | s1 | |
|
||||
| string.cpp:500:17:500:18 | ref arg s1 | string.cpp:503:7:503:8 | s1 | |
|
||||
| string.cpp:500:17:500:18 | s1 | string.cpp:500:20:500:24 | call to begin | TAINT |
|
||||
| string.cpp:500:17:500:37 | call to basic_string | string.cpp:505:7:505:8 | s3 | |
|
||||
| string.cpp:500:20:500:24 | call to begin | string.cpp:500:17:500:37 | call to basic_string | TAINT |
|
||||
| string.cpp:500:29:500:30 | ref arg s1 | string.cpp:503:7:503:8 | s1 | |
|
||||
| string.cpp:500:29:500:30 | s1 | string.cpp:500:32:500:34 | call to end | TAINT |
|
||||
| string.cpp:500:32:500:34 | call to end | string.cpp:500:17:500:37 | call to basic_string | TAINT |
|
||||
| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:501:29:501:30 | s2 | |
|
||||
| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:504:7:504:8 | s2 | |
|
||||
| string.cpp:501:17:501:18 | s2 | string.cpp:501:20:501:24 | call to begin | TAINT |
|
||||
| string.cpp:501:17:501:37 | call to basic_string | string.cpp:506:7:506:8 | s4 | |
|
||||
| string.cpp:501:20:501:24 | call to begin | string.cpp:501:17:501:37 | call to basic_string | TAINT |
|
||||
| string.cpp:501:29:501:30 | ref arg s2 | string.cpp:504:7:504:8 | s2 | |
|
||||
| string.cpp:501:29:501:30 | s2 | string.cpp:501:32:501:34 | call to end | TAINT |
|
||||
| string.cpp:501:32:501:34 | call to end | string.cpp:501:17:501:37 | call to basic_string | TAINT |
|
||||
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | |
|
||||
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | |
|
||||
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | |
|
||||
@@ -1874,6 +2100,9 @@
|
||||
| vector.cpp:17:26:17:32 | source1 | vector.cpp:17:21:17:33 | call to vector | TAINT |
|
||||
| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator* | TAINT |
|
||||
| vector.cpp:19:14:19:14 | (__begin) | vector.cpp:19:14:19:14 | call to operator++ | TAINT |
|
||||
| vector.cpp:19:14:19:14 | (__end) | vector.cpp:19:14:19:14 | call to iterator | |
|
||||
| vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to begin | TAINT |
|
||||
| vector.cpp:19:14:19:14 | (__range) | vector.cpp:19:14:19:14 | call to end | TAINT |
|
||||
| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
| vector.cpp:19:14:19:14 | call to begin | vector.cpp:19:14:19:14 | (__begin) | |
|
||||
@@ -1889,12 +2118,14 @@
|
||||
| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:23:55:23:55 | v | |
|
||||
| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:27:15:27:15 | v | |
|
||||
| vector.cpp:23:38:23:38 | ref arg v | vector.cpp:35:1:35:1 | v | |
|
||||
| vector.cpp:23:38:23:38 | v | vector.cpp:23:40:23:44 | call to begin | TAINT |
|
||||
| vector.cpp:23:40:23:44 | call to begin | vector.cpp:23:49:23:50 | it | |
|
||||
| vector.cpp:23:40:23:44 | call to begin | vector.cpp:23:66:23:67 | it | |
|
||||
| vector.cpp:23:40:23:44 | call to begin | vector.cpp:24:9:24:10 | it | |
|
||||
| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:23:55:23:55 | v | |
|
||||
| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:27:15:27:15 | v | |
|
||||
| vector.cpp:23:55:23:55 | ref arg v | vector.cpp:35:1:35:1 | v | |
|
||||
| vector.cpp:23:55:23:55 | v | vector.cpp:23:57:23:59 | call to end | TAINT |
|
||||
| vector.cpp:23:66:23:67 | it | vector.cpp:23:64:23:64 | call to operator++ | TAINT |
|
||||
| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:49:23:50 | it | |
|
||||
| vector.cpp:23:66:23:67 | ref arg it | vector.cpp:23:66:23:67 | it | |
|
||||
@@ -1902,6 +2133,9 @@
|
||||
| vector.cpp:24:9:24:10 | it | vector.cpp:24:8:24:8 | call to operator* | TAINT |
|
||||
| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator* | TAINT |
|
||||
| vector.cpp:27:15:27:15 | (__begin) | vector.cpp:27:15:27:15 | call to operator++ | TAINT |
|
||||
| vector.cpp:27:15:27:15 | (__end) | vector.cpp:27:15:27:15 | call to iterator | |
|
||||
| vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to begin | TAINT |
|
||||
| vector.cpp:27:15:27:15 | (__range) | vector.cpp:27:15:27:15 | call to end | TAINT |
|
||||
| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
| vector.cpp:27:15:27:15 | call to begin | vector.cpp:27:15:27:15 | (__begin) | |
|
||||
@@ -1919,6 +2153,8 @@
|
||||
| vector.cpp:31:38:31:44 | source1 | vector.cpp:31:33:31:45 | call to vector | TAINT |
|
||||
| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator* | TAINT |
|
||||
| vector.cpp:32:21:32:21 | (__begin) | vector.cpp:32:21:32:21 | call to operator++ | TAINT |
|
||||
| vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to begin | TAINT |
|
||||
| vector.cpp:32:21:32:21 | (__range) | vector.cpp:32:21:32:21 | call to end | TAINT |
|
||||
| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | |
|
||||
| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | |
|
||||
| vector.cpp:32:21:32:21 | call to begin | vector.cpp:32:21:32:21 | (__begin) | |
|
||||
@@ -1977,7 +2213,7 @@
|
||||
| vector.cpp:38:62:38:64 | call to vector | vector.cpp:75:7:75:8 | v6 | |
|
||||
| vector.cpp:38:62:38:64 | call to vector | vector.cpp:76:7:76:8 | v6 | |
|
||||
| vector.cpp:38:62:38:64 | call to vector | vector.cpp:101:1:101:1 | v6 | |
|
||||
| vector.cpp:38:70:38:72 | call to vector | vector.cpp:79:33:79:34 | v7 | |
|
||||
| vector.cpp:38:70:38:72 | call to vector | vector.cpp:80:41:80:42 | v7 | |
|
||||
| vector.cpp:38:70:38:72 | call to vector | vector.cpp:81:3:81:4 | v7 | |
|
||||
| vector.cpp:38:70:38:72 | call to vector | vector.cpp:83:7:83:8 | v7 | |
|
||||
| vector.cpp:38:70:38:72 | call to vector | vector.cpp:84:7:84:8 | v7 | |
|
||||
@@ -2166,12 +2402,21 @@
|
||||
| vector.cpp:76:7:76:8 | v6 | vector.cpp:76:10:76:13 | call to data | TAINT |
|
||||
| vector.cpp:76:10:76:13 | call to data | vector.cpp:76:7:76:18 | access to array | TAINT |
|
||||
| vector.cpp:76:17:76:17 | 2 | vector.cpp:76:7:76:18 | access to array | TAINT |
|
||||
| vector.cpp:79:33:79:34 | v7 | vector.cpp:80:41:80:43 | v7c | |
|
||||
| vector.cpp:80:45:80:49 | call to begin | vector.cpp:81:13:81:14 | it | |
|
||||
| vector.cpp:80:40:80:50 | call to iterator | vector.cpp:81:13:81:14 | it | |
|
||||
| vector.cpp:80:41:80:42 | ref arg v7 | vector.cpp:81:3:81:4 | v7 | |
|
||||
| vector.cpp:80:41:80:42 | ref arg v7 | vector.cpp:83:7:83:8 | v7 | |
|
||||
| vector.cpp:80:41:80:42 | ref arg v7 | vector.cpp:84:7:84:8 | v7 | |
|
||||
| vector.cpp:80:41:80:42 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | |
|
||||
| vector.cpp:80:41:80:42 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | |
|
||||
| vector.cpp:80:41:80:42 | v7 | vector.cpp:80:44:80:48 | call to begin | TAINT |
|
||||
| vector.cpp:80:44:80:48 | call to begin | vector.cpp:80:40:80:50 | call to iterator | TAINT |
|
||||
| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:83:7:83:8 | v7 | |
|
||||
| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:84:7:84:8 | v7 | |
|
||||
| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | |
|
||||
| vector.cpp:81:3:81:4 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | |
|
||||
| vector.cpp:81:3:81:4 | v7 | vector.cpp:81:6:81:11 | call to insert | TAINT |
|
||||
| vector.cpp:81:17:81:22 | call to source | vector.cpp:81:3:81:4 | ref arg v7 | TAINT |
|
||||
| vector.cpp:81:17:81:22 | call to source | vector.cpp:81:6:81:11 | call to insert | TAINT |
|
||||
| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:84:7:84:8 | v7 | |
|
||||
| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:85:7:85:8 | v7 | |
|
||||
| vector.cpp:83:7:83:8 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | |
|
||||
@@ -2181,11 +2426,13 @@
|
||||
| vector.cpp:85:7:85:8 | ref arg v7 | vector.cpp:101:1:101:1 | v7 | |
|
||||
| vector.cpp:85:7:85:8 | v7 | vector.cpp:85:10:85:13 | call to back | TAINT |
|
||||
| vector.cpp:88:33:88:34 | v8 | vector.cpp:89:41:89:43 | v8c | |
|
||||
| vector.cpp:89:41:89:43 | v8c | vector.cpp:89:45:89:49 | call to begin | TAINT |
|
||||
| vector.cpp:89:45:89:49 | call to begin | vector.cpp:90:13:90:14 | it | |
|
||||
| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:92:7:92:8 | v8 | |
|
||||
| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:93:7:93:8 | v8 | |
|
||||
| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:94:7:94:8 | v8 | |
|
||||
| vector.cpp:90:3:90:4 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | |
|
||||
| vector.cpp:90:3:90:4 | v8 | vector.cpp:90:6:90:11 | call to insert | TAINT |
|
||||
| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:93:7:93:8 | v8 | |
|
||||
| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:94:7:94:8 | v8 | |
|
||||
| vector.cpp:92:7:92:8 | ref arg v8 | vector.cpp:101:1:101:1 | v8 | |
|
||||
@@ -2563,15 +2810,24 @@
|
||||
| vector.cpp:249:3:249:4 | ref arg v4 | vector.cpp:262:2:262:2 | v4 | |
|
||||
| vector.cpp:249:13:249:14 | ref arg v1 | vector.cpp:249:25:249:26 | v1 | |
|
||||
| vector.cpp:249:13:249:14 | ref arg v1 | vector.cpp:277:1:277:1 | v1 | |
|
||||
| vector.cpp:249:13:249:14 | v1 | vector.cpp:249:16:249:20 | call to begin | TAINT |
|
||||
| vector.cpp:249:16:249:20 | call to begin | vector.cpp:249:3:249:4 | ref arg v4 | TAINT |
|
||||
| vector.cpp:249:25:249:26 | ref arg v1 | vector.cpp:277:1:277:1 | v1 | |
|
||||
| vector.cpp:249:25:249:26 | v1 | vector.cpp:249:28:249:30 | call to end | TAINT |
|
||||
| vector.cpp:249:28:249:30 | call to end | vector.cpp:249:3:249:4 | ref arg v4 | TAINT |
|
||||
| vector.cpp:250:3:250:4 | ref arg v5 | vector.cpp:258:8:258:9 | v5 | |
|
||||
| vector.cpp:250:3:250:4 | ref arg v5 | vector.cpp:262:2:262:2 | v5 | |
|
||||
| vector.cpp:250:13:250:14 | ref arg v3 | vector.cpp:250:25:250:26 | v3 | |
|
||||
| vector.cpp:250:13:250:14 | ref arg v3 | vector.cpp:251:8:251:9 | v3 | |
|
||||
| vector.cpp:250:13:250:14 | ref arg v3 | vector.cpp:277:1:277:1 | v3 | |
|
||||
| vector.cpp:250:13:250:14 | v3 | vector.cpp:250:16:250:20 | call to begin | TAINT |
|
||||
| vector.cpp:250:16:250:20 | call to begin | vector.cpp:250:3:250:4 | ref arg v5 | TAINT |
|
||||
| vector.cpp:250:25:250:26 | ref arg v3 | vector.cpp:251:8:251:9 | v3 | |
|
||||
| vector.cpp:250:25:250:26 | ref arg v3 | vector.cpp:277:1:277:1 | v3 | |
|
||||
| vector.cpp:250:25:250:26 | v3 | vector.cpp:250:28:250:30 | call to end | TAINT |
|
||||
| vector.cpp:250:28:250:30 | call to end | vector.cpp:250:3:250:4 | ref arg v5 | TAINT |
|
||||
| vector.cpp:251:8:251:9 | ref arg v3 | vector.cpp:277:1:277:1 | v3 | |
|
||||
| vector.cpp:251:8:251:9 | v3 | vector.cpp:251:11:251:15 | call to begin | TAINT |
|
||||
| vector.cpp:251:11:251:15 | call to begin | vector.cpp:251:3:251:17 | ... = ... | |
|
||||
| vector.cpp:251:11:251:15 | call to begin | vector.cpp:252:3:252:4 | i1 | |
|
||||
| vector.cpp:251:11:251:15 | call to begin | vector.cpp:253:8:253:9 | i1 | |
|
||||
@@ -2590,6 +2846,10 @@
|
||||
| vector.cpp:254:3:254:4 | ref arg i2 | vector.cpp:260:8:260:9 | i2 | |
|
||||
| vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:261:8:261:9 | v6 | |
|
||||
| vector.cpp:255:3:255:4 | ref arg v6 | vector.cpp:262:2:262:2 | v6 | |
|
||||
| vector.cpp:255:13:255:14 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT |
|
||||
| vector.cpp:255:13:255:14 | i1 | vector.cpp:255:13:255:14 | call to iterator | |
|
||||
| vector.cpp:255:17:255:18 | call to iterator | vector.cpp:255:3:255:4 | ref arg v6 | TAINT |
|
||||
| vector.cpp:255:17:255:18 | i2 | vector.cpp:255:17:255:18 | call to iterator | |
|
||||
| vector.cpp:257:8:257:9 | ref arg v4 | vector.cpp:262:2:262:2 | v4 | |
|
||||
| vector.cpp:258:8:258:9 | ref arg v5 | vector.cpp:262:2:262:2 | v5 | |
|
||||
| vector.cpp:261:8:261:9 | ref arg v6 | vector.cpp:262:2:262:2 | v6 | |
|
||||
@@ -2661,3 +2921,136 @@
|
||||
| vector.cpp:292:7:292:8 | v2 | vector.cpp:292:10:292:13 | call to data | TAINT |
|
||||
| vector.cpp:292:10:292:13 | call to data | vector.cpp:292:7:292:18 | access to array | TAINT |
|
||||
| vector.cpp:292:17:292:17 | 2 | vector.cpp:292:7:292:18 | access to array | TAINT |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:305:7:305:7 | a | |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:305:16:305:16 | a | |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:306:7:306:7 | a | |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:311:25:311:25 | a | |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:311:36:311:36 | a | |
|
||||
| vector.cpp:298:19:298:19 | call to vector | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:299:19:299:19 | call to vector | vector.cpp:305:25:305:25 | b | |
|
||||
| vector.cpp:299:19:299:19 | call to vector | vector.cpp:305:36:305:36 | b | |
|
||||
| vector.cpp:299:19:299:19 | call to vector | vector.cpp:313:1:313:1 | b | |
|
||||
| vector.cpp:300:19:300:19 | call to vector | vector.cpp:308:7:308:7 | c | |
|
||||
| vector.cpp:300:19:300:19 | call to vector | vector.cpp:308:16:308:16 | c | |
|
||||
| vector.cpp:300:19:300:19 | call to vector | vector.cpp:309:7:309:7 | c | |
|
||||
| vector.cpp:300:19:300:19 | call to vector | vector.cpp:313:1:313:1 | c | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:303:2:303:2 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:308:25:308:25 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:308:36:308:36 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:311:7:311:7 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:311:16:311:16 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:301:19:301:19 | call to vector | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:308:25:308:25 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:308:36:308:36 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:311:7:311:7 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:311:16:311:16 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:303:2:303:2 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:303:14:303:19 | call to source | vector.cpp:303:2:303:2 | ref arg d | TAINT |
|
||||
| vector.cpp:305:7:305:7 | a | vector.cpp:305:9:305:14 | call to insert | TAINT |
|
||||
| vector.cpp:305:7:305:7 | ref arg a | vector.cpp:306:7:306:7 | a | |
|
||||
| vector.cpp:305:7:305:7 | ref arg a | vector.cpp:311:25:311:25 | a | |
|
||||
| vector.cpp:305:7:305:7 | ref arg a | vector.cpp:311:36:311:36 | a | |
|
||||
| vector.cpp:305:7:305:7 | ref arg a | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:305:16:305:16 | a | vector.cpp:305:18:305:20 | call to end | TAINT |
|
||||
| vector.cpp:305:16:305:16 | ref arg a | vector.cpp:305:7:305:7 | a | |
|
||||
| vector.cpp:305:16:305:16 | ref arg a | vector.cpp:306:7:306:7 | a | |
|
||||
| vector.cpp:305:16:305:16 | ref arg a | vector.cpp:311:25:311:25 | a | |
|
||||
| vector.cpp:305:16:305:16 | ref arg a | vector.cpp:311:36:311:36 | a | |
|
||||
| vector.cpp:305:16:305:16 | ref arg a | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:305:18:305:20 | call to end | vector.cpp:305:16:305:22 | call to iterator | TAINT |
|
||||
| vector.cpp:305:25:305:25 | b | vector.cpp:305:27:305:31 | call to begin | TAINT |
|
||||
| vector.cpp:305:25:305:25 | ref arg b | vector.cpp:305:36:305:36 | b | |
|
||||
| vector.cpp:305:25:305:25 | ref arg b | vector.cpp:313:1:313:1 | b | |
|
||||
| vector.cpp:305:27:305:31 | call to begin | vector.cpp:305:7:305:7 | ref arg a | TAINT |
|
||||
| vector.cpp:305:27:305:31 | call to begin | vector.cpp:305:9:305:14 | call to insert | TAINT |
|
||||
| vector.cpp:305:36:305:36 | b | vector.cpp:305:38:305:40 | call to end | TAINT |
|
||||
| vector.cpp:305:36:305:36 | ref arg b | vector.cpp:313:1:313:1 | b | |
|
||||
| vector.cpp:305:38:305:40 | call to end | vector.cpp:305:7:305:7 | ref arg a | TAINT |
|
||||
| vector.cpp:305:38:305:40 | call to end | vector.cpp:305:9:305:14 | call to insert | TAINT |
|
||||
| vector.cpp:306:7:306:7 | ref arg a | vector.cpp:311:25:311:25 | a | |
|
||||
| vector.cpp:306:7:306:7 | ref arg a | vector.cpp:311:36:311:36 | a | |
|
||||
| vector.cpp:306:7:306:7 | ref arg a | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:308:7:308:7 | c | vector.cpp:308:9:308:14 | call to insert | TAINT |
|
||||
| vector.cpp:308:7:308:7 | ref arg c | vector.cpp:309:7:309:7 | c | |
|
||||
| vector.cpp:308:7:308:7 | ref arg c | vector.cpp:313:1:313:1 | c | |
|
||||
| vector.cpp:308:16:308:16 | c | vector.cpp:308:18:308:20 | call to end | TAINT |
|
||||
| vector.cpp:308:16:308:16 | ref arg c | vector.cpp:308:7:308:7 | c | |
|
||||
| vector.cpp:308:16:308:16 | ref arg c | vector.cpp:309:7:309:7 | c | |
|
||||
| vector.cpp:308:16:308:16 | ref arg c | vector.cpp:313:1:313:1 | c | |
|
||||
| vector.cpp:308:18:308:20 | call to end | vector.cpp:308:16:308:22 | call to iterator | TAINT |
|
||||
| vector.cpp:308:25:308:25 | d | vector.cpp:308:27:308:31 | call to begin | TAINT |
|
||||
| vector.cpp:308:25:308:25 | ref arg d | vector.cpp:308:36:308:36 | d | |
|
||||
| vector.cpp:308:25:308:25 | ref arg d | vector.cpp:311:7:311:7 | d | |
|
||||
| vector.cpp:308:25:308:25 | ref arg d | vector.cpp:311:16:311:16 | d | |
|
||||
| vector.cpp:308:25:308:25 | ref arg d | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:308:25:308:25 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:308:27:308:31 | call to begin | vector.cpp:308:7:308:7 | ref arg c | TAINT |
|
||||
| vector.cpp:308:27:308:31 | call to begin | vector.cpp:308:9:308:14 | call to insert | TAINT |
|
||||
| vector.cpp:308:36:308:36 | d | vector.cpp:308:38:308:40 | call to end | TAINT |
|
||||
| vector.cpp:308:36:308:36 | ref arg d | vector.cpp:311:7:311:7 | d | |
|
||||
| vector.cpp:308:36:308:36 | ref arg d | vector.cpp:311:16:311:16 | d | |
|
||||
| vector.cpp:308:36:308:36 | ref arg d | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:308:36:308:36 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:308:38:308:40 | call to end | vector.cpp:308:7:308:7 | ref arg c | TAINT |
|
||||
| vector.cpp:308:38:308:40 | call to end | vector.cpp:308:9:308:14 | call to insert | TAINT |
|
||||
| vector.cpp:309:7:309:7 | ref arg c | vector.cpp:313:1:313:1 | c | |
|
||||
| vector.cpp:311:7:311:7 | d | vector.cpp:311:9:311:14 | call to insert | TAINT |
|
||||
| vector.cpp:311:7:311:7 | ref arg d | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:311:7:311:7 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:311:16:311:16 | d | vector.cpp:311:18:311:20 | call to end | TAINT |
|
||||
| vector.cpp:311:16:311:16 | ref arg d | vector.cpp:311:7:311:7 | d | |
|
||||
| vector.cpp:311:16:311:16 | ref arg d | vector.cpp:312:7:312:7 | d | |
|
||||
| vector.cpp:311:16:311:16 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:311:18:311:20 | call to end | vector.cpp:311:16:311:22 | call to iterator | TAINT |
|
||||
| vector.cpp:311:25:311:25 | a | vector.cpp:311:27:311:31 | call to begin | TAINT |
|
||||
| vector.cpp:311:25:311:25 | ref arg a | vector.cpp:311:36:311:36 | a | |
|
||||
| vector.cpp:311:25:311:25 | ref arg a | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:311:27:311:31 | call to begin | vector.cpp:311:7:311:7 | ref arg d | TAINT |
|
||||
| vector.cpp:311:27:311:31 | call to begin | vector.cpp:311:9:311:14 | call to insert | TAINT |
|
||||
| vector.cpp:311:36:311:36 | a | vector.cpp:311:38:311:40 | call to end | TAINT |
|
||||
| vector.cpp:311:36:311:36 | ref arg a | vector.cpp:313:1:313:1 | a | |
|
||||
| vector.cpp:311:38:311:40 | call to end | vector.cpp:311:7:311:7 | ref arg d | TAINT |
|
||||
| vector.cpp:311:38:311:40 | call to end | vector.cpp:311:9:311:14 | call to insert | TAINT |
|
||||
| vector.cpp:312:7:312:7 | ref arg d | vector.cpp:313:1:313:1 | d | |
|
||||
| vector.cpp:316:19:316:20 | call to vector | vector.cpp:320:22:320:23 | v1 | |
|
||||
| vector.cpp:316:19:316:20 | call to vector | vector.cpp:320:34:320:35 | v1 | |
|
||||
| vector.cpp:316:19:316:20 | call to vector | vector.cpp:323:7:323:8 | v1 | |
|
||||
| vector.cpp:316:19:316:20 | call to vector | vector.cpp:327:1:327:1 | v1 | |
|
||||
| vector.cpp:317:19:317:20 | call to vector | vector.cpp:318:2:318:3 | v2 | |
|
||||
| vector.cpp:317:19:317:20 | call to vector | vector.cpp:321:22:321:23 | v2 | |
|
||||
| vector.cpp:317:19:317:20 | call to vector | vector.cpp:321:34:321:35 | v2 | |
|
||||
| vector.cpp:317:19:317:20 | call to vector | vector.cpp:324:7:324:8 | v2 | |
|
||||
| vector.cpp:317:19:317:20 | call to vector | vector.cpp:327:1:327:1 | v2 | |
|
||||
| vector.cpp:318:2:318:3 | ref arg v2 | vector.cpp:321:22:321:23 | v2 | |
|
||||
| vector.cpp:318:2:318:3 | ref arg v2 | vector.cpp:321:34:321:35 | v2 | |
|
||||
| vector.cpp:318:2:318:3 | ref arg v2 | vector.cpp:324:7:324:8 | v2 | |
|
||||
| vector.cpp:318:2:318:3 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
|
||||
| vector.cpp:318:15:318:20 | call to source | vector.cpp:318:2:318:3 | ref arg v2 | TAINT |
|
||||
| vector.cpp:320:22:320:23 | ref arg v1 | vector.cpp:320:34:320:35 | v1 | |
|
||||
| vector.cpp:320:22:320:23 | ref arg v1 | vector.cpp:323:7:323:8 | v1 | |
|
||||
| vector.cpp:320:22:320:23 | ref arg v1 | vector.cpp:327:1:327:1 | v1 | |
|
||||
| vector.cpp:320:22:320:23 | v1 | vector.cpp:320:25:320:29 | call to begin | TAINT |
|
||||
| vector.cpp:320:22:320:42 | call to vector | vector.cpp:325:7:325:8 | v3 | |
|
||||
| vector.cpp:320:22:320:42 | call to vector | vector.cpp:327:1:327:1 | v3 | |
|
||||
| vector.cpp:320:25:320:29 | call to begin | vector.cpp:320:22:320:42 | call to vector | TAINT |
|
||||
| vector.cpp:320:34:320:35 | ref arg v1 | vector.cpp:323:7:323:8 | v1 | |
|
||||
| vector.cpp:320:34:320:35 | ref arg v1 | vector.cpp:327:1:327:1 | v1 | |
|
||||
| vector.cpp:320:34:320:35 | v1 | vector.cpp:320:37:320:39 | call to end | TAINT |
|
||||
| vector.cpp:320:37:320:39 | call to end | vector.cpp:320:22:320:42 | call to vector | TAINT |
|
||||
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:321:34:321:35 | v2 | |
|
||||
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:324:7:324:8 | v2 | |
|
||||
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
|
||||
| vector.cpp:321:22:321:23 | v2 | vector.cpp:321:25:321:29 | call to begin | TAINT |
|
||||
| vector.cpp:321:22:321:42 | call to vector | vector.cpp:326:7:326:8 | v4 | |
|
||||
| vector.cpp:321:22:321:42 | call to vector | vector.cpp:327:1:327:1 | v4 | |
|
||||
| vector.cpp:321:25:321:29 | call to begin | vector.cpp:321:22:321:42 | call to vector | TAINT |
|
||||
| vector.cpp:321:34:321:35 | ref arg v2 | vector.cpp:324:7:324:8 | v2 | |
|
||||
| vector.cpp:321:34:321:35 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
|
||||
| vector.cpp:321:34:321:35 | v2 | vector.cpp:321:37:321:39 | call to end | TAINT |
|
||||
| vector.cpp:321:37:321:39 | call to end | vector.cpp:321:22:321:42 | call to vector | TAINT |
|
||||
| vector.cpp:323:7:323:8 | ref arg v1 | vector.cpp:327:1:327:1 | v1 | |
|
||||
| vector.cpp:324:7:324:8 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
|
||||
| vector.cpp:325:7:325:8 | ref arg v3 | vector.cpp:327:1:327:1 | v3 | |
|
||||
| vector.cpp:326:7:326:8 | ref arg v4 | vector.cpp:327:1:327:1 | v4 | |
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
template<class T>
|
||||
struct remove_const { typedef T type; };
|
||||
|
||||
template<class T>
|
||||
struct remove_const<const T> { typedef T type; };
|
||||
|
||||
// `remove_const_t<T>` removes any `const` specifier from `T`
|
||||
template<class T>
|
||||
using remove_const_t = typename remove_const<T>::type;
|
||||
|
||||
// --- iterator ---
|
||||
|
||||
namespace std {
|
||||
@@ -16,6 +26,9 @@ namespace std {
|
||||
struct iterator {
|
||||
typedef Category iterator_category;
|
||||
|
||||
iterator();
|
||||
iterator(iterator<Category, remove_const_t<value_type> > const &other); // non-const -> const conversion constructor
|
||||
|
||||
iterator &operator++();
|
||||
iterator operator++(int);
|
||||
iterator &operator--();
|
||||
@@ -45,13 +58,12 @@ namespace std
|
||||
|
||||
typedef size_t streamsize;
|
||||
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
typedef size_t size_type;
|
||||
};
|
||||
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
@@ -63,6 +75,7 @@ namespace std
|
||||
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
charT* data() noexcept;
|
||||
@@ -87,12 +100,15 @@ namespace std
|
||||
basic_string& append(const basic_string& str);
|
||||
basic_string& append(const charT* s);
|
||||
basic_string& append(size_type n, charT c);
|
||||
template<class InputIterator>
|
||||
/* constexpr */ basic_string& append(InputIterator first, InputIterator last);
|
||||
template<class InputIterator> basic_string& append(InputIterator first, InputIterator last);
|
||||
basic_string& assign(const basic_string& str);
|
||||
basic_string& assign(size_type n, charT c);
|
||||
template<class InputIterator> basic_string& assign(InputIterator first, InputIterator last);
|
||||
basic_string& insert(size_type pos, const basic_string& str);
|
||||
basic_string& insert(size_type pos, size_type n, charT c);
|
||||
basic_string& insert(size_type pos, const charT* s);
|
||||
iterator insert(const_iterator p, size_type n, charT c);
|
||||
template<class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last);
|
||||
basic_string& replace(size_type pos1, size_type n1, const basic_string& str);
|
||||
basic_string& replace(size_type pos1, size_type n1, size_type n2, charT c);
|
||||
size_type copy(charT* s, size_type n, size_type pos = 0) const;
|
||||
@@ -156,7 +172,10 @@ namespace std {
|
||||
vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
|
||||
explicit vector(const Allocator&) noexcept;
|
||||
explicit vector(size_type n, const Allocator& = Allocator());
|
||||
vector(size_type n, const T& value, const Allocator& = Allocator());
|
||||
vector(size_type n, const T& value, const Allocator& = Allocator());
|
||||
template<class InputIterator, class IteratorCategory = typename InputIterator::iterator_category> vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
|
||||
// use of `iterator_category` makes sure InputIterator is (probably) an iterator, and not an `int` or
|
||||
// similar that should match a different overload (SFINAE).
|
||||
~vector();
|
||||
|
||||
vector& operator=(const vector& x);
|
||||
@@ -191,6 +210,7 @@ namespace std {
|
||||
iterator insert(const_iterator position, const T& x);
|
||||
iterator insert(const_iterator position, T&& x);
|
||||
iterator insert(const_iterator position, size_type n, const T& x);
|
||||
template<class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last);
|
||||
|
||||
void swap(vector&) noexcept/*(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value)*/;
|
||||
|
||||
|
||||
@@ -413,3 +413,95 @@ void test_string_iterators() {
|
||||
sink(*i9); // tainted
|
||||
}
|
||||
}
|
||||
|
||||
void test_string_insert_more()
|
||||
{
|
||||
std::string s1("aa");
|
||||
std::string s2("bb");
|
||||
char *cs1 = "cc";
|
||||
char *cs2 = source();
|
||||
|
||||
sink(s1.insert(0, cs1));
|
||||
sink(s1);
|
||||
|
||||
sink(s2.insert(0, cs2)); // tainted
|
||||
sink(s2); // tainted
|
||||
}
|
||||
|
||||
void sink(std::string::iterator);
|
||||
|
||||
void test_string_iterator_methods()
|
||||
{
|
||||
{
|
||||
std::string a("aa");
|
||||
std::string b("bb");
|
||||
|
||||
sink(a.insert(a.begin(), 10, 'x'));
|
||||
sink(a);
|
||||
|
||||
sink(b.insert(b.begin(), 10, ns_char::source())); // tainted
|
||||
sink(b); // tainted
|
||||
}
|
||||
|
||||
{
|
||||
std::string c("cc");
|
||||
std::string d("dd");
|
||||
std::string s1("11");
|
||||
std::string s2(source());
|
||||
|
||||
sink(c.insert(c.end(), s1.begin(), s1.end()));
|
||||
sink(c);
|
||||
|
||||
sink(d.insert(d.end(), s2.begin(), s2.end())); // tainted
|
||||
sink(d); // tainted
|
||||
|
||||
sink(s2.insert(s2.end(), s1.begin(), s1.end())); // tainted
|
||||
sink(s2); // tainted
|
||||
}
|
||||
|
||||
{
|
||||
std::string e("ee");
|
||||
std::string f("ff");
|
||||
std::string s3("33");
|
||||
std::string s4(source());
|
||||
|
||||
sink(e.append(s3.begin(), s3.end()));
|
||||
sink(e);
|
||||
|
||||
sink(f.append(s4.begin(), s4.end())); // tainted
|
||||
sink(f); // tainted
|
||||
|
||||
sink(s4.append(s3.begin(), s3.end())); // tainted
|
||||
sink(s4); // tainted
|
||||
}
|
||||
|
||||
{
|
||||
std::string g("gg");
|
||||
std::string h("hh");
|
||||
std::string s5("55");
|
||||
std::string s6(source());
|
||||
|
||||
sink(g.assign(s5.cbegin(), s5.cend()));
|
||||
sink(g);
|
||||
|
||||
sink(h.assign(s6.cbegin(), s6.cend())); // tainted
|
||||
sink(h); // tainted
|
||||
|
||||
sink(s6.assign(s5.cbegin(), s5.cend()));
|
||||
sink(s6); // [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void test_constructors_more() {
|
||||
char *cs1 = "abc";
|
||||
char *cs2 = source();
|
||||
std::string s1(cs1);
|
||||
std::string s2(cs2);
|
||||
std::string s3(s1.begin(), s1.end());
|
||||
std::string s4(s2.begin(), s2.end());
|
||||
|
||||
sink(s1);
|
||||
sink(s2); // tainted
|
||||
sink(s3);
|
||||
sink(s4); // tainted
|
||||
}
|
||||
|
||||
@@ -121,6 +121,23 @@
|
||||
| string.cpp:407:8:407:8 | call to operator* | string.cpp:387:18:387:23 | call to source |
|
||||
| string.cpp:409:8:409:8 | call to operator* | string.cpp:387:18:387:23 | call to source |
|
||||
| string.cpp:413:8:413:8 | call to operator* | string.cpp:387:18:387:23 | call to source |
|
||||
| string.cpp:427:10:427:15 | call to insert | string.cpp:422:14:422:19 | call to source |
|
||||
| string.cpp:428:7:428:8 | s2 | string.cpp:422:14:422:19 | call to source |
|
||||
| string.cpp:442:10:442:15 | call to insert | string.cpp:442:32:442:46 | call to source |
|
||||
| string.cpp:443:8:443:8 | b | string.cpp:442:32:442:46 | call to source |
|
||||
| string.cpp:455:10:455:15 | call to insert | string.cpp:450:18:450:23 | call to source |
|
||||
| string.cpp:456:8:456:8 | d | string.cpp:450:18:450:23 | call to source |
|
||||
| string.cpp:458:11:458:16 | call to insert | string.cpp:450:18:450:23 | call to source |
|
||||
| string.cpp:459:8:459:9 | s2 | string.cpp:450:18:450:23 | call to source |
|
||||
| string.cpp:471:10:471:15 | call to append | string.cpp:466:18:466:23 | call to source |
|
||||
| string.cpp:472:8:472:8 | f | string.cpp:466:18:466:23 | call to source |
|
||||
| string.cpp:474:11:474:16 | call to append | string.cpp:466:18:466:23 | call to source |
|
||||
| string.cpp:475:8:475:9 | s4 | string.cpp:466:18:466:23 | call to source |
|
||||
| string.cpp:487:10:487:15 | call to assign | string.cpp:482:18:482:23 | call to source |
|
||||
| string.cpp:488:8:488:8 | h | string.cpp:482:18:482:23 | call to source |
|
||||
| string.cpp:491:8:491:9 | s6 | string.cpp:482:18:482:23 | call to source |
|
||||
| string.cpp:504:7:504:8 | s2 | string.cpp:497:14:497:19 | call to source |
|
||||
| string.cpp:506:7:506:8 | s4 | string.cpp:497:14:497:19 | call to source |
|
||||
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
|
||||
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
|
||||
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |
|
||||
@@ -228,6 +245,7 @@
|
||||
| taint.cpp:471:7:471:7 | y | taint.cpp:462:6:462:11 | call to source |
|
||||
| taint.cpp:485:7:485:10 | line | taint.cpp:480:26:480:32 | source1 |
|
||||
| vector.cpp:20:8:20:8 | x | vector.cpp:16:43:16:49 | source1 |
|
||||
| vector.cpp:24:8:24:8 | call to operator* | vector.cpp:16:43:16:49 | source1 |
|
||||
| vector.cpp:28:8:28:8 | x | vector.cpp:16:43:16:49 | source1 |
|
||||
| vector.cpp:33:8:33:8 | x | vector.cpp:16:43:16:49 | source1 |
|
||||
| vector.cpp:52:7:52:8 | v2 | vector.cpp:51:10:51:15 | call to source |
|
||||
@@ -247,6 +265,9 @@
|
||||
| vector.cpp:72:10:72:13 | call to back | vector.cpp:69:15:69:20 | call to source |
|
||||
| vector.cpp:75:7:75:8 | v6 | vector.cpp:74:17:74:22 | call to source |
|
||||
| vector.cpp:76:7:76:18 | access to array | vector.cpp:74:17:74:22 | call to source |
|
||||
| vector.cpp:83:7:83:8 | v7 | vector.cpp:81:17:81:22 | call to source |
|
||||
| vector.cpp:84:10:84:14 | call to front | vector.cpp:81:17:81:22 | call to source |
|
||||
| vector.cpp:85:10:85:13 | call to back | vector.cpp:81:17:81:22 | call to source |
|
||||
| vector.cpp:97:7:97:8 | v9 | vector.cpp:96:13:96:18 | call to source |
|
||||
| vector.cpp:98:10:98:11 | call to at | vector.cpp:96:13:96:18 | call to source |
|
||||
| vector.cpp:99:10:99:11 | call to at | vector.cpp:96:13:96:18 | call to source |
|
||||
@@ -268,6 +289,10 @@
|
||||
| vector.cpp:201:13:201:13 | call to operator[] | vector.cpp:200:14:200:19 | call to source |
|
||||
| vector.cpp:242:7:242:8 | v2 | vector.cpp:238:17:238:30 | call to source |
|
||||
| vector.cpp:243:7:243:8 | v3 | vector.cpp:239:15:239:20 | call to source |
|
||||
| vector.cpp:258:8:258:9 | v5 | vector.cpp:239:15:239:20 | call to source |
|
||||
| vector.cpp:259:8:259:9 | i1 | vector.cpp:239:15:239:20 | call to source |
|
||||
| vector.cpp:260:8:260:9 | i2 | vector.cpp:239:15:239:20 | call to source |
|
||||
| vector.cpp:261:8:261:9 | v6 | vector.cpp:239:15:239:20 | call to source |
|
||||
| vector.cpp:273:8:273:9 | v7 | vector.cpp:269:18:269:31 | call to source |
|
||||
| vector.cpp:274:8:274:9 | v8 | vector.cpp:270:18:270:35 | call to source |
|
||||
| vector.cpp:275:8:275:9 | v9 | vector.cpp:271:18:271:34 | call to source |
|
||||
@@ -277,3 +302,9 @@
|
||||
| vector.cpp:290:7:290:8 | v2 | vector.cpp:289:17:289:30 | call to source |
|
||||
| vector.cpp:291:10:291:13 | call to data | vector.cpp:289:17:289:30 | call to source |
|
||||
| vector.cpp:292:7:292:18 | access to array | vector.cpp:289:17:289:30 | call to source |
|
||||
| vector.cpp:308:9:308:14 | call to insert | vector.cpp:303:14:303:19 | call to source |
|
||||
| vector.cpp:309:7:309:7 | c | vector.cpp:303:14:303:19 | call to source |
|
||||
| vector.cpp:311:9:311:14 | call to insert | vector.cpp:303:14:303:19 | call to source |
|
||||
| vector.cpp:312:7:312:7 | d | vector.cpp:303:14:303:19 | call to source |
|
||||
| vector.cpp:324:7:324:8 | v2 | vector.cpp:318:15:318:20 | call to source |
|
||||
| vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source |
|
||||
|
||||
@@ -121,6 +121,23 @@
|
||||
| string.cpp:407:8:407:8 | string.cpp:387:18:387:23 | AST only |
|
||||
| string.cpp:409:8:409:8 | string.cpp:387:18:387:23 | AST only |
|
||||
| string.cpp:413:8:413:8 | string.cpp:387:18:387:23 | AST only |
|
||||
| string.cpp:427:10:427:15 | string.cpp:422:14:422:19 | AST only |
|
||||
| string.cpp:428:7:428:8 | string.cpp:422:14:422:19 | AST only |
|
||||
| string.cpp:442:10:442:15 | string.cpp:442:32:442:46 | AST only |
|
||||
| string.cpp:443:8:443:8 | string.cpp:442:32:442:46 | AST only |
|
||||
| string.cpp:455:10:455:15 | string.cpp:450:18:450:23 | AST only |
|
||||
| string.cpp:456:8:456:8 | string.cpp:450:18:450:23 | AST only |
|
||||
| string.cpp:458:11:458:16 | string.cpp:450:18:450:23 | AST only |
|
||||
| string.cpp:459:8:459:9 | string.cpp:450:18:450:23 | AST only |
|
||||
| string.cpp:471:10:471:15 | string.cpp:466:18:466:23 | AST only |
|
||||
| string.cpp:472:8:472:8 | string.cpp:466:18:466:23 | AST only |
|
||||
| string.cpp:474:11:474:16 | string.cpp:466:18:466:23 | AST only |
|
||||
| string.cpp:475:8:475:9 | string.cpp:466:18:466:23 | AST only |
|
||||
| string.cpp:487:10:487:15 | string.cpp:482:18:482:23 | AST only |
|
||||
| string.cpp:488:8:488:8 | string.cpp:482:18:482:23 | AST only |
|
||||
| string.cpp:491:8:491:9 | string.cpp:482:18:482:23 | AST only |
|
||||
| string.cpp:504:7:504:8 | string.cpp:497:14:497:19 | AST only |
|
||||
| string.cpp:506:7:506:8 | string.cpp:497:14:497:19 | AST only |
|
||||
| swap1.cpp:78:12:78:16 | swap1.cpp:69:23:69:23 | AST only |
|
||||
| swap1.cpp:87:13:87:17 | swap1.cpp:82:16:82:21 | AST only |
|
||||
| swap1.cpp:88:13:88:17 | swap1.cpp:81:27:81:28 | AST only |
|
||||
@@ -162,6 +179,7 @@
|
||||
| taint.cpp:447:9:447:17 | taint.cpp:445:14:445:28 | AST only |
|
||||
| taint.cpp:471:7:471:7 | taint.cpp:462:6:462:11 | AST only |
|
||||
| vector.cpp:20:8:20:8 | vector.cpp:16:43:16:49 | AST only |
|
||||
| vector.cpp:24:8:24:8 | vector.cpp:16:43:16:49 | AST only |
|
||||
| vector.cpp:28:8:28:8 | vector.cpp:16:43:16:49 | AST only |
|
||||
| vector.cpp:33:8:33:8 | vector.cpp:16:43:16:49 | AST only |
|
||||
| vector.cpp:52:7:52:8 | vector.cpp:51:10:51:15 | AST only |
|
||||
@@ -181,6 +199,9 @@
|
||||
| vector.cpp:72:10:72:13 | vector.cpp:69:15:69:20 | AST only |
|
||||
| vector.cpp:75:7:75:8 | vector.cpp:74:17:74:22 | AST only |
|
||||
| vector.cpp:76:7:76:18 | vector.cpp:74:17:74:22 | AST only |
|
||||
| vector.cpp:83:7:83:8 | vector.cpp:81:17:81:22 | AST only |
|
||||
| vector.cpp:84:10:84:14 | vector.cpp:81:17:81:22 | AST only |
|
||||
| vector.cpp:85:10:85:13 | vector.cpp:81:17:81:22 | AST only |
|
||||
| vector.cpp:97:7:97:8 | vector.cpp:96:13:96:18 | AST only |
|
||||
| vector.cpp:98:10:98:11 | vector.cpp:96:13:96:18 | AST only |
|
||||
| vector.cpp:99:10:99:11 | vector.cpp:96:13:96:18 | AST only |
|
||||
@@ -203,6 +224,10 @@
|
||||
| vector.cpp:201:13:201:13 | vector.cpp:200:14:200:19 | AST only |
|
||||
| vector.cpp:242:7:242:8 | vector.cpp:238:17:238:30 | AST only |
|
||||
| vector.cpp:243:7:243:8 | vector.cpp:239:15:239:20 | AST only |
|
||||
| vector.cpp:258:8:258:9 | vector.cpp:239:15:239:20 | AST only |
|
||||
| vector.cpp:259:8:259:9 | vector.cpp:239:15:239:20 | AST only |
|
||||
| vector.cpp:260:8:260:9 | vector.cpp:239:15:239:20 | AST only |
|
||||
| vector.cpp:261:8:261:9 | vector.cpp:239:15:239:20 | AST only |
|
||||
| vector.cpp:273:8:273:9 | vector.cpp:269:18:269:31 | AST only |
|
||||
| vector.cpp:274:8:274:9 | vector.cpp:270:18:270:35 | AST only |
|
||||
| vector.cpp:275:8:275:9 | vector.cpp:271:18:271:34 | AST only |
|
||||
@@ -212,3 +237,9 @@
|
||||
| vector.cpp:290:7:290:8 | vector.cpp:289:17:289:30 | AST only |
|
||||
| vector.cpp:291:10:291:13 | vector.cpp:289:17:289:30 | AST only |
|
||||
| vector.cpp:292:7:292:18 | vector.cpp:289:17:289:30 | AST only |
|
||||
| vector.cpp:308:9:308:14 | vector.cpp:303:14:303:19 | AST only |
|
||||
| vector.cpp:309:7:309:7 | vector.cpp:303:14:303:19 | AST only |
|
||||
| vector.cpp:311:9:311:14 | vector.cpp:303:14:303:19 | AST only |
|
||||
| vector.cpp:312:7:312:7 | vector.cpp:303:14:303:19 | AST only |
|
||||
| vector.cpp:324:7:324:8 | vector.cpp:318:15:318:20 | AST only |
|
||||
| vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only |
|
||||
|
||||
@@ -21,7 +21,7 @@ void test_range_based_for_loop_vector(int source1) {
|
||||
}
|
||||
|
||||
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
|
||||
sink(*it); // tainted [NOT DETECTED]
|
||||
sink(*it); // tainted
|
||||
}
|
||||
|
||||
for(int& x : v) {
|
||||
@@ -75,14 +75,14 @@ void test_element_taint(int x) {
|
||||
sink(v6); // tainted
|
||||
sink(v6.data()[2]); // tainted
|
||||
|
||||
|
||||
{
|
||||
const std::vector<int> &v7c = v7; // (workaround because our iterators don't convert to const_iterator)
|
||||
std::vector<int>::const_iterator it = v7c.begin();
|
||||
std::vector<int>::const_iterator it = v7.begin();
|
||||
v7.insert(it, source());
|
||||
}
|
||||
sink(v7); // tainted [NOT DETECTED]
|
||||
sink(v7.front()); // tainted [NOT DETECTED]
|
||||
sink(v7.back());
|
||||
sink(v7); // tainted
|
||||
sink(v7.front()); // tainted
|
||||
sink(v7.back()); // [FALSE POSITIVE]
|
||||
|
||||
{
|
||||
const std::vector<int> &v8c = v8;
|
||||
@@ -255,10 +255,10 @@ void test_vector_assign() {
|
||||
v6.assign(i1, i2);
|
||||
|
||||
sink(v4);
|
||||
sink(v5); // tainted [NOT DETECTED]
|
||||
sink(i1); // tainted [NOT DETECTED]
|
||||
sink(i2); // tainted [NOT DETECTED]
|
||||
sink(v6); // tainted [NOT DETECTED]
|
||||
sink(v5); // tainted
|
||||
sink(i1); // tainted
|
||||
sink(i2); // tainted
|
||||
sink(v6); // tainted
|
||||
}
|
||||
|
||||
{
|
||||
@@ -291,3 +291,37 @@ void test_data_more() {
|
||||
sink(v2.data()); // tainted
|
||||
sink(v2.data()[2]); // tainted
|
||||
}
|
||||
|
||||
void sink(std::vector<int>::iterator);
|
||||
|
||||
void test_vector_insert() {
|
||||
std::vector<int> a;
|
||||
std::vector<int> b;
|
||||
std::vector<int> c;
|
||||
std::vector<int> d;
|
||||
|
||||
d.push_back(source());
|
||||
|
||||
sink(a.insert(a.end(), b.begin(), b.end()));
|
||||
sink(a);
|
||||
|
||||
sink(c.insert(c.end(), d.begin(), d.end())); // tainted
|
||||
sink(c); // tainted
|
||||
|
||||
sink(d.insert(d.end(), a.begin(), a.end())); // tainted
|
||||
sink(d); // tainted
|
||||
}
|
||||
|
||||
void test_constructors_more() {
|
||||
std::vector<int> v1;
|
||||
std::vector<int> v2;
|
||||
v2.push_back(source());
|
||||
|
||||
std::vector<int> v3(v1.begin(), v1.end());
|
||||
std::vector<int> v4(v2.begin(), v2.end());
|
||||
|
||||
sink(v1);
|
||||
sink(v2); // tainted
|
||||
sink(v3);
|
||||
sink(v4); // tainted
|
||||
}
|
||||
|
||||
@@ -532,6 +532,37 @@
|
||||
| test.c:530:3:530:3 | i | -2147483648 |
|
||||
| test.c:530:10:530:11 | sc | 1 |
|
||||
| test.c:532:7:532:7 | i | -128 |
|
||||
| test.c:539:7:539:7 | n | 0 |
|
||||
| test.c:541:7:541:7 | n | 0 |
|
||||
| test.c:542:9:542:9 | n | 1 |
|
||||
| test.c:545:7:545:7 | n | 0 |
|
||||
| test.c:546:9:546:9 | n | 1 |
|
||||
| test.c:548:9:548:9 | n | 0 |
|
||||
| test.c:551:8:551:8 | n | 0 |
|
||||
| test.c:552:9:552:9 | n | 0 |
|
||||
| test.c:554:9:554:9 | n | 0 |
|
||||
| test.c:557:10:557:10 | n | 0 |
|
||||
| test.c:558:5:558:5 | n | 1 |
|
||||
| test.c:561:7:561:7 | n | 0 |
|
||||
| test.c:565:7:565:7 | n | -32768 |
|
||||
| test.c:568:7:568:7 | n | 0 |
|
||||
| test.c:569:9:569:9 | n | 0 |
|
||||
| test.c:571:9:571:9 | n | 1 |
|
||||
| test.c:574:7:574:7 | n | 0 |
|
||||
| test.c:575:9:575:9 | n | 0 |
|
||||
| test.c:577:9:577:9 | n | 0 |
|
||||
| test.c:580:10:580:10 | n | 0 |
|
||||
| test.c:581:5:581:5 | n | 1 |
|
||||
| test.c:584:7:584:7 | n | 0 |
|
||||
| test.c:588:7:588:7 | n | -32768 |
|
||||
| test.c:589:9:589:9 | n | -32768 |
|
||||
| test.c:590:11:590:11 | n | 0 |
|
||||
| test.c:594:7:594:7 | n | -32768 |
|
||||
| test.c:595:13:595:13 | n | 5 |
|
||||
| test.c:598:9:598:9 | n | 6 |
|
||||
| test.c:601:7:601:7 | n | -32768 |
|
||||
| test.c:601:22:601:22 | n | -32767 |
|
||||
| test.c:602:9:602:9 | n | -32766 |
|
||||
| test.cpp:10:7:10:7 | b | -2147483648 |
|
||||
| test.cpp:11:5:11:5 | x | -2147483648 |
|
||||
| test.cpp:13:10:13:10 | x | -2147483648 |
|
||||
|
||||
@@ -533,3 +533,72 @@ int mul_by_constant(int i, int j) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int notequal_type_endpoint(unsigned n) {
|
||||
out(n); // 0 ..
|
||||
|
||||
if (n > 0) {
|
||||
out(n); // 1 ..
|
||||
}
|
||||
|
||||
if (n != 0) {
|
||||
out(n); // 1 ..
|
||||
} else {
|
||||
out(n); // 0 .. 0
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
out(n); // 0 .. 0
|
||||
} else {
|
||||
out(n); // 1 .. [BUG: lower bound is deduced to be 0]
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
n--; // 1 ..
|
||||
}
|
||||
|
||||
out(n); // 0 .. 0
|
||||
}
|
||||
|
||||
void notequal_refinement(short n) {
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
if (n == 0) {
|
||||
out(n); // 0 .. 0
|
||||
} else {
|
||||
out(n); // 1 ..
|
||||
}
|
||||
|
||||
if (n) {
|
||||
out(n); // 1 .. [BUG: lower bound is deduced to be 0]
|
||||
} else {
|
||||
out(n); // 0 .. 0
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
n--; // 1 ..
|
||||
}
|
||||
|
||||
out(n); // 0 .. 0
|
||||
}
|
||||
|
||||
void notequal_variations(short n, float f) {
|
||||
if (n != 0) {
|
||||
if (n >= 0) {
|
||||
out(n); // 1 .. [BUG: we can't handle `!=` coming first]
|
||||
}
|
||||
}
|
||||
|
||||
if (n >= 5) {
|
||||
if (2 * n - 10 == 0) { // Same as `n == 10/2` (modulo overflow)
|
||||
return;
|
||||
}
|
||||
out(n); // 6 ..
|
||||
}
|
||||
|
||||
if (n != -32768 && n != -32767) {
|
||||
out(n); // -32766 ..
|
||||
}
|
||||
}
|
||||
@@ -532,6 +532,37 @@
|
||||
| test.c:530:3:530:3 | i | 2147483647 |
|
||||
| test.c:530:10:530:11 | sc | 1 |
|
||||
| test.c:532:7:532:7 | i | 127 |
|
||||
| test.c:539:7:539:7 | n | 4294967295 |
|
||||
| test.c:541:7:541:7 | n | 4294967295 |
|
||||
| test.c:542:9:542:9 | n | 4294967295 |
|
||||
| test.c:545:7:545:7 | n | 4294967295 |
|
||||
| test.c:546:9:546:9 | n | 4294967295 |
|
||||
| test.c:548:9:548:9 | n | 0 |
|
||||
| test.c:551:8:551:8 | n | 4294967295 |
|
||||
| test.c:552:9:552:9 | n | 4294967295 |
|
||||
| test.c:554:9:554:9 | n | 4294967295 |
|
||||
| test.c:557:10:557:10 | n | 4294967295 |
|
||||
| test.c:558:5:558:5 | n | 4294967295 |
|
||||
| test.c:561:7:561:7 | n | 0 |
|
||||
| test.c:565:7:565:7 | n | 32767 |
|
||||
| test.c:568:7:568:7 | n | 32767 |
|
||||
| test.c:569:9:569:9 | n | 0 |
|
||||
| test.c:571:9:571:9 | n | 32767 |
|
||||
| test.c:574:7:574:7 | n | 32767 |
|
||||
| test.c:575:9:575:9 | n | 32767 |
|
||||
| test.c:577:9:577:9 | n | 32767 |
|
||||
| test.c:580:10:580:10 | n | 32767 |
|
||||
| test.c:581:5:581:5 | n | 32767 |
|
||||
| test.c:584:7:584:7 | n | 0 |
|
||||
| test.c:588:7:588:7 | n | 32767 |
|
||||
| test.c:589:9:589:9 | n | 32767 |
|
||||
| test.c:590:11:590:11 | n | 32767 |
|
||||
| test.c:594:7:594:7 | n | 32767 |
|
||||
| test.c:595:13:595:13 | n | 32767 |
|
||||
| test.c:598:9:598:9 | n | 32767 |
|
||||
| test.c:601:7:601:7 | n | 32767 |
|
||||
| test.c:601:22:601:22 | n | 32767 |
|
||||
| test.c:602:9:602:9 | n | 32767 |
|
||||
| test.cpp:10:7:10:7 | b | 2147483647 |
|
||||
| test.cpp:11:5:11:5 | x | 2147483647 |
|
||||
| test.cpp:13:10:13:10 | x | 2147483647 |
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.internal.CFG
|
||||
|
||||
class DestructorCallEnhanced extends DestructorCall {
|
||||
override string toString() {
|
||||
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
|
||||
then
|
||||
result =
|
||||
"call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
|
||||
this.getTarget().getName()
|
||||
else result = super.toString()
|
||||
}
|
||||
}
|
||||
|
||||
predicate differentEdge(ControlFlowNode n1, ControlFlowNode n2, string msg) {
|
||||
successors(n1, n2) and
|
||||
not qlCFGSuccessor(n1, n2) and
|
||||
msg = "Standard edge, only from extractor"
|
||||
or
|
||||
not successors(n1, n2) and
|
||||
qlCFGSuccessor(n1, n2) and
|
||||
msg = "Standard edge, only from QL"
|
||||
or
|
||||
truecond_base(n1, n2) and
|
||||
not qlCFGTrueSuccessor(n1, n2) and
|
||||
msg = "True edge, only from extractor"
|
||||
or
|
||||
not truecond_base(n1, n2) and
|
||||
qlCFGTrueSuccessor(n1, n2) and
|
||||
msg = "True edge, only from QL"
|
||||
or
|
||||
falsecond_base(n1, n2) and
|
||||
not qlCFGFalseSuccessor(n1, n2) and
|
||||
msg = "False edge, only from extractor"
|
||||
or
|
||||
not falsecond_base(n1, n2) and
|
||||
qlCFGFalseSuccessor(n1, n2) and
|
||||
msg = "False edge, only from QL"
|
||||
}
|
||||
|
||||
predicate differentScope(Element e) {
|
||||
exists(ControlFlowNode n1 |
|
||||
getScopeElement(n1) = e and
|
||||
differentEdge(n1, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isInFunction(ControlFlowNode x, Function f) {
|
||||
f = x.getControlFlowScope()
|
||||
or
|
||||
exists(ControlFlowNode y |
|
||||
successors(unresolveElement(x), unresolveElement(y))
|
||||
or
|
||||
successors(unresolveElement(y), unresolveElement(x))
|
||||
|
|
||||
isInFunction(y, f)
|
||||
)
|
||||
}
|
||||
|
||||
Element getScopeElement(ControlFlowNode x) {
|
||||
isInFunction(x, result)
|
||||
or
|
||||
not isInFunction(x, _) and
|
||||
result = x.getFile()
|
||||
}
|
||||
|
||||
string getScopeName(ControlFlowNode x) {
|
||||
exists(Function scope | scope = getScopeElement(x) |
|
||||
differentScope(scope) and
|
||||
result =
|
||||
scope.getFile().getBaseName().splitAt(".", 0) + "__" +
|
||||
scope.getQualifiedName().replaceAll("::", "_")
|
||||
)
|
||||
or
|
||||
exists(File scope | scope = getScopeElement(x) |
|
||||
differentScope(scope) and
|
||||
result = scope.getBaseName()
|
||||
)
|
||||
}
|
||||
|
||||
module QLCFG {
|
||||
private predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
|
||||
isEdge = false and x = y and label = x.toString()
|
||||
}
|
||||
|
||||
private predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
|
||||
exists(string truelabel, string falselabel |
|
||||
isEdge = true and
|
||||
qlCFGSuccessor(x, y) and
|
||||
(if qlCFGTrueSuccessor(x, y) then truelabel = "T" else truelabel = "") and
|
||||
(if qlCFGFalseSuccessor(x, y) then falselabel = "F" else falselabel = "") and
|
||||
label = truelabel + falselabel
|
||||
)
|
||||
}
|
||||
|
||||
predicate qltestGraph(
|
||||
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
|
||||
string label
|
||||
) {
|
||||
scopeElement = getScopeElement(x) and
|
||||
scopeString = getScopeName(x) + "_ql" and
|
||||
(
|
||||
isNode(isEdge, x, y, label)
|
||||
or
|
||||
isSuccessor(isEdge, x, y, label)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module ExtractorCFG {
|
||||
predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
|
||||
isEdge = false and x = y and label = x.toString()
|
||||
}
|
||||
|
||||
predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
|
||||
exists(string truelabel, string falselabel |
|
||||
isEdge = true and
|
||||
successors(x, y) and
|
||||
(if truecond_base(x, y) then truelabel = "T" else truelabel = "") and
|
||||
(if falsecond_base(x, y) then falselabel = "F" else falselabel = "") and
|
||||
label = truelabel + falselabel
|
||||
)
|
||||
}
|
||||
|
||||
predicate qltestGraph(
|
||||
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
|
||||
string label
|
||||
) {
|
||||
scopeElement = getScopeElement(x) and
|
||||
scopeString = getScopeName(x) + "_extractor" and
|
||||
(
|
||||
isNode(isEdge, x, y, label)
|
||||
or
|
||||
isSuccessor(isEdge, x, y, label)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AllCFG {
|
||||
predicate qltestGraph(
|
||||
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
|
||||
string label
|
||||
) {
|
||||
QLCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label)
|
||||
or
|
||||
ExtractorCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label)
|
||||
}
|
||||
}
|
||||
2110
cpp/upgrades/098850d25c4e9d417eb74c1bef9deb2f9d2dc417/old.dbscheme
Normal file
2110
cpp/upgrades/098850d25c4e9d417eb74c1bef9deb2f9d2dc417/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove the old CFG tables
|
||||
compatibility: full
|
||||
|
||||
@@ -345,6 +345,7 @@ namespace Semmle.Autobuild.CSharp.Tests
|
||||
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = "";
|
||||
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}";
|
||||
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
|
||||
Actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = isWindows ? "win64" : "linux64";
|
||||
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";
|
||||
Actions.GetEnvironmentVariable["SEMMLE_JAVA_HOME"] = @"C:\odasa\tools\java";
|
||||
Actions.GetEnvironmentVariable["SEMMLE_PLATFORM_TOOLS"] = @"C:\odasa\tools";
|
||||
@@ -497,7 +498,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
|
||||
[Fact]
|
||||
public void TestLinuxBuildlessExtractionSuccess()
|
||||
{
|
||||
Actions.RunProcess[@"C:\odasa\tools/csharp/Semmle.Extraction.CSharp.Standalone --references:."] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone --references:."] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0;
|
||||
Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0;
|
||||
Actions.FileExists["csharp.log"] = true;
|
||||
@@ -513,7 +514,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
|
||||
[Fact]
|
||||
public void TestLinuxBuildlessExtractionFailed()
|
||||
{
|
||||
Actions.RunProcess[@"C:\odasa\tools/csharp/Semmle.Extraction.CSharp.Standalone --references:."] = 10;
|
||||
Actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone --references:."] = 10;
|
||||
Actions.FileExists["csharp.log"] = true;
|
||||
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_TRAP_DIR"] = "";
|
||||
Actions.GetEnvironmentVariable["CODEQL_EXTRACTOR_CSHARP_SOURCE_ARCHIVE_DIR"] = "";
|
||||
@@ -527,7 +528,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
|
||||
[Fact]
|
||||
public void TestLinuxBuildlessExtractionSolution()
|
||||
{
|
||||
Actions.RunProcess[@"C:\odasa\tools/csharp/Semmle.Extraction.CSharp.Standalone foo.sln --references:."] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln --references:."] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0;
|
||||
Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0;
|
||||
Actions.FileExists["csharp.log"] = true;
|
||||
@@ -835,7 +836,7 @@ Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.Ap
|
||||
[Fact]
|
||||
public void TestSkipNugetBuildless()
|
||||
{
|
||||
Actions.RunProcess[@"C:\odasa\tools/csharp/Semmle.Extraction.CSharp.Standalone foo.sln --references:. --skip-nuget"] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\csharp/tools/linux64/Semmle.Extraction.CSharp.Standalone foo.sln --references:. --skip-nuget"] = 0;
|
||||
Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0;
|
||||
Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0;
|
||||
Actions.FileExists["csharp.log"] = true;
|
||||
|
||||
@@ -11,10 +11,15 @@ namespace Semmle.Autobuild.CSharp
|
||||
{
|
||||
BuildScript GetCommand(string? solution)
|
||||
{
|
||||
if (builder.SemmlePlatformTools is null)
|
||||
string standalone;
|
||||
if (builder.CodeQLExtractorLangRoot is object && builder.CodeQlPlatform is object) {
|
||||
standalone = builder.Actions.PathCombine(builder.CodeQLExtractorLangRoot, "tools", builder.CodeQlPlatform, "Semmle.Extraction.CSharp.Standalone");
|
||||
} else if (builder.SemmlePlatformTools is object) {
|
||||
standalone = builder.Actions.PathCombine(builder.SemmlePlatformTools, "csharp", "Semmle.Extraction.CSharp.Standalone");
|
||||
} else {
|
||||
return BuildScript.Failure;
|
||||
}
|
||||
|
||||
var standalone = builder.Actions.PathCombine(builder.SemmlePlatformTools, "csharp", "Semmle.Extraction.CSharp.Standalone");
|
||||
var cmd = new CommandBuilder(builder.Actions);
|
||||
cmd.RunCommand(standalone);
|
||||
|
||||
|
||||
@@ -193,6 +193,8 @@ namespace Semmle.Autobuild.Shared
|
||||
SemmleDist = Actions.GetEnvironmentVariable("SEMMLE_DIST");
|
||||
SemmlePlatformTools = Actions.GetEnvironmentVariable("SEMMLE_PLATFORM_TOOLS");
|
||||
|
||||
CodeQlPlatform = Actions.GetEnvironmentVariable("CODEQL_PLATFORM");
|
||||
|
||||
JavaHome =
|
||||
Actions.GetEnvironmentVariable("CODEQL_JAVA_HOME") ??
|
||||
Actions.GetEnvironmentVariable("SEMMLE_JAVA_HOME") ??
|
||||
@@ -271,7 +273,7 @@ namespace Semmle.Autobuild.Shared
|
||||
/// <summary>
|
||||
/// Value of CODEQL_EXTRACTOR_<LANG>_ROOT environment variable.
|
||||
/// </summary>
|
||||
private string? CodeQLExtractorLangRoot { get; }
|
||||
public string? CodeQLExtractorLangRoot { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Value of SEMMLE_DIST environment variable.
|
||||
@@ -287,6 +289,11 @@ namespace Semmle.Autobuild.Shared
|
||||
/// </summary>
|
||||
public string? SemmlePlatformTools { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Value of CODEQL_PLATFORM environment variable.
|
||||
/// </summary>
|
||||
public string? CodeQlPlatform { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The absolute path of the odasa executable.
|
||||
/// null if we are running in CodeQL.
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
trapFile = trapWriter.TrapFile;
|
||||
if (nocache || !System.IO.File.Exists(trapFile))
|
||||
{
|
||||
var cx = extractor.CreateContext(null, trapWriter, null);
|
||||
var cx = extractor.CreateContext(null, trapWriter, null, false);
|
||||
ExtractCIL(cx, assemblyPath, extractPdbs);
|
||||
extracted = true;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,12 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
public readonly ILogger Logger;
|
||||
|
||||
public Analyser(IProgressMonitor pm, ILogger logger)
|
||||
public readonly bool AddAssemblyTrapPrefix;
|
||||
|
||||
public Analyser(IProgressMonitor pm, ILogger logger, bool addAssemblyTrapPrefix)
|
||||
{
|
||||
Logger = logger;
|
||||
AddAssemblyTrapPrefix = addAssemblyTrapPrefix;
|
||||
Logger.Log(Severity.Info, "EXTRACTION STARTING at {0}", DateTime.Now);
|
||||
stopWatch.Start();
|
||||
progressMonitor = pm;
|
||||
@@ -231,7 +234,7 @@ namespace Semmle.Extraction.CSharp
|
||||
var projectLayout = layout.LookupProjectOrDefault(assemblyPath);
|
||||
var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true, options.TrapCompression);
|
||||
compilationTrapFile = trapWriter; // Dispose later
|
||||
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true));
|
||||
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true), AddAssemblyTrapPrefix);
|
||||
|
||||
compilationEntity = new Entities.Compilation(cx, cwd, args);
|
||||
}
|
||||
@@ -286,7 +289,7 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
if (assembly != null)
|
||||
{
|
||||
var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath, false));
|
||||
var cx = extractor.CreateContext(c, trapWriter, new AssemblyScope(assembly, assemblyPath, false), AddAssemblyTrapPrefix);
|
||||
|
||||
foreach (var module in assembly.Modules)
|
||||
{
|
||||
@@ -372,7 +375,7 @@ namespace Semmle.Extraction.CSharp
|
||||
|
||||
if (!upToDate)
|
||||
{
|
||||
Context cx = extractor.CreateContext(compilation.Clone(), trapWriter, new SourceScope(tree));
|
||||
Context cx = extractor.CreateContext(compilation.Clone(), trapWriter, new SourceScope(tree), AddAssemblyTrapPrefix);
|
||||
Populators.CompilationUnit.Extract(cx, tree.GetRoot());
|
||||
cx.PopulateAll();
|
||||
cx.ExtractComments(cx.CommentGenerator);
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static Accessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
AccessorFactory.Instance.CreateEntity(cx, symbol);
|
||||
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor>
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
Context.TrapWriter.Writer.commentblock_binding(this, entity, binding);
|
||||
}
|
||||
|
||||
public static CommentBlock Create(Context cx, ICommentBlock block) => CommentBlockFactory.Instance.CreateEntity(cx, block);
|
||||
public static CommentBlock Create(Context cx, ICommentBlock block) => CommentBlockFactory.Instance.CreateEntity(cx, block, block);
|
||||
|
||||
class CommentBlockFactory : ICachedEntityFactory<ICommentBlock, CommentBlock>
|
||||
{
|
||||
|
||||
@@ -129,7 +129,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write(";commentline");
|
||||
}
|
||||
|
||||
static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw) => CommentLineFactory.Instance.CreateEntity(cx, loc, type, text, raw);
|
||||
static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw)
|
||||
{
|
||||
var init = (loc, type, text, raw);
|
||||
return CommentLineFactory.Instance.CreateEntity(cx, init, init);
|
||||
}
|
||||
|
||||
class CommentLineFactory : ICachedEntityFactory<(Microsoft.CodeAnalysis.Location, CommentLineType, string, string), CommentLine>
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
case MethodKind.StaticConstructor:
|
||||
case MethodKind.Constructor:
|
||||
return ConstructorFactory.Instance.CreateEntity(cx, constructor);
|
||||
return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor);
|
||||
default:
|
||||
throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor");
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
: base(cx, init) { }
|
||||
|
||||
public new static Conversion Create(Context cx, IMethodSymbol symbol) =>
|
||||
ConversionFactory.Instance.CreateEntity(cx, symbol);
|
||||
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static Destructor Create(Context cx, IMethodSymbol symbol) =>
|
||||
DestructorFactory.Instance.CreateEntity(cx, symbol);
|
||||
DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class DestructorFactory : ICachedEntityFactory<IMethodSymbol, Destructor>
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
TypeMention.Create(Context, syntaxType, this, type);
|
||||
}
|
||||
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class EventFactory : ICachedEntityFactory<IEventSymbol, Event>
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static EventAccessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
EventAccessorFactory.Instance.CreateEntity(cx, symbol);
|
||||
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class EventAccessorFactory : ICachedEntityFactory<IMethodSymbol, EventAccessor>
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType()));
|
||||
}
|
||||
|
||||
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field);
|
||||
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field);
|
||||
|
||||
// Do not populate backing fields.
|
||||
// Populate Tuple fields.
|
||||
@@ -101,6 +101,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Type.Type);
|
||||
trapFile.Write(" ");
|
||||
trapFile.WriteSubId(ContainingType);
|
||||
trapFile.Write('.');
|
||||
trapFile.Write(symbol.Name);
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
TypeMention.Create(Context, syntax.Type, this, type);
|
||||
}
|
||||
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop);
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write('*');
|
||||
}
|
||||
|
||||
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field);
|
||||
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field);
|
||||
|
||||
class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFunction>
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public static LocalVariable Create(Context cx, ISymbol local)
|
||||
{
|
||||
return LocalVariableFactory.Instance.CreateEntity(cx, local);
|
||||
return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local);
|
||||
}
|
||||
|
||||
void DefineConstantValue(TextWriter trapFile)
|
||||
|
||||
@@ -108,6 +108,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
/// </summary>
|
||||
protected static void BuildMethodId(Method m, TextWriter trapFile)
|
||||
{
|
||||
m.symbol.ReturnType.BuildOrWriteId(m.Context, trapFile, m.symbol);
|
||||
trapFile.Write(" ");
|
||||
|
||||
trapFile.WriteSubId(m.ContainingType);
|
||||
|
||||
AddExplicitInterfaceQualifierToId(m.Context, trapFile, m.symbol.ExplicitInterfaceImplementations);
|
||||
@@ -129,7 +132,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
// Type arguments with different nullability can result in
|
||||
// a constructed method with different nullability of its parameters and return type,
|
||||
// so we need to create a distinct database entity for it.
|
||||
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); });
|
||||
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { ta.Symbol.BuildOrWriteId(m.Context, tb0, m.symbol); trapFile.Write((int)ta.Nullability); });
|
||||
trapFile.Write('>');
|
||||
}
|
||||
}
|
||||
@@ -163,65 +166,21 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
BuildMethodId(this, trapFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an appropriate label ID to the trap builder <paramref name="trapFile"/>
|
||||
/// for the type <paramref name="type"/> belonging to the signature of method
|
||||
/// <paramref name="method"/>.
|
||||
///
|
||||
/// For methods without type parameters this will always add the key of the
|
||||
/// corresponding type.
|
||||
///
|
||||
/// For methods with type parameters, this will add the key of the
|
||||
/// corresponding type if the type does *not* contain one of the method
|
||||
/// type parameters, otherwise it will add a textual representation of
|
||||
/// the type. This distinction is required because type parameter IDs
|
||||
/// refer to their declaring methods.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// <code>
|
||||
/// int Count<T>(IEnumerable<T> items)
|
||||
/// </code>
|
||||
///
|
||||
/// The label definitions for <code>Count</code> (<code>#4</code>) and <code>T</code>
|
||||
/// (<code>#5</code>) will look like:
|
||||
///
|
||||
/// <code>
|
||||
/// #1=<label for System.Int32>
|
||||
/// #2=<label for type containing Count>
|
||||
/// #3=<label for IEnumerable`1>
|
||||
/// #4=@"{#1} {#2}.Count`2(#3<T>);method"
|
||||
/// #5=@"{#4}T;typeparameter"
|
||||
/// </code>
|
||||
///
|
||||
/// Note how <code>int</code> is referenced in the label definition <code>#3</code> for
|
||||
/// <code>Count</code>, while <code>T[]</code> is represented textually in order
|
||||
/// to make the reference to <code>#3</code> in the label definition <code>#4</code> for
|
||||
/// <code>T</code> valid.
|
||||
/// </summary>
|
||||
protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type)
|
||||
{
|
||||
if (type.ContainsTypeParameters(cx, method))
|
||||
type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
|
||||
else
|
||||
trapFile.WriteSubId(Type.Create(cx, type));
|
||||
}
|
||||
|
||||
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method)
|
||||
{
|
||||
trapFile.Write('(');
|
||||
int index = 0;
|
||||
|
||||
if (method.MethodKind == MethodKind.ReducedExtension)
|
||||
{
|
||||
trapFile.WriteSeparator(",", ref index);
|
||||
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType);
|
||||
}
|
||||
var @params = method.MethodKind == MethodKind.ReducedExtension
|
||||
? method.ReducedFrom.Parameters
|
||||
: method.Parameters;
|
||||
|
||||
foreach (var param in method.Parameters)
|
||||
foreach (var param in @params)
|
||||
{
|
||||
trapFile.WriteSeparator(",", ref index);
|
||||
AddSignatureTypeToId(cx, trapFile, method, param.Type);
|
||||
param.Type.BuildOrWriteId(cx, trapFile, method);
|
||||
trapFile.Write(" ");
|
||||
trapFile.Write(param.Name);
|
||||
switch (param.RefKind)
|
||||
{
|
||||
case RefKind.Out:
|
||||
@@ -245,9 +204,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
|
||||
{
|
||||
if (explicitInterfaceImplementations.Any())
|
||||
{
|
||||
trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string Name => symbol.Name;
|
||||
|
||||
@@ -5,37 +5,16 @@ using System.Reflection;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Provide a "Key" object to allow modifiers to exist as entities in the extractor
|
||||
/// hash map. (Raw strings would work as keys but might clash with other types).
|
||||
/// </summary>
|
||||
class ModifierKey : Object
|
||||
class Modifier : Extraction.CachedEntity<string>
|
||||
{
|
||||
public readonly string name;
|
||||
|
||||
public ModifierKey(string m)
|
||||
{
|
||||
name = m;
|
||||
}
|
||||
|
||||
public override bool Equals(Object obj)
|
||||
{
|
||||
return obj.GetType() == GetType() && name == ((ModifierKey)obj).name;
|
||||
}
|
||||
|
||||
public override int GetHashCode() => 13 * name.GetHashCode();
|
||||
}
|
||||
|
||||
class Modifier : Extraction.CachedEntity<ModifierKey>
|
||||
{
|
||||
Modifier(Context cx, ModifierKey init)
|
||||
Modifier(Context cx, string init)
|
||||
: base(cx, init) { }
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.Write(symbol.name);
|
||||
trapFile.Write(symbol);
|
||||
trapFile.Write(";modifier");
|
||||
}
|
||||
|
||||
@@ -43,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
trapFile.modifiers(Label, symbol.name);
|
||||
trapFile.modifiers(Label, symbol);
|
||||
}
|
||||
|
||||
public static string AccessbilityModifier(Accessibility access)
|
||||
@@ -152,17 +131,22 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static Modifier Create(Context cx, string modifier) =>
|
||||
ModifierFactory.Instance.CreateEntity(cx, new ModifierKey(modifier));
|
||||
public static Modifier Create(Context cx, string modifier)
|
||||
{
|
||||
return ModifierFactory.Instance.CreateEntity(cx, (typeof(Modifier), modifier), modifier);
|
||||
}
|
||||
|
||||
public static Modifier Create(Context cx, Accessibility access) =>
|
||||
ModifierFactory.Instance.CreateEntity(cx, new ModifierKey(AccessbilityModifier(access)));
|
||||
public static Modifier Create(Context cx, Accessibility access)
|
||||
{
|
||||
var modifier = AccessbilityModifier(access);
|
||||
return ModifierFactory.Instance.CreateEntity(cx, (typeof(Modifier), modifier), modifier);
|
||||
}
|
||||
|
||||
class ModifierFactory : ICachedEntityFactory<ModifierKey, Modifier>
|
||||
class ModifierFactory : ICachedEntityFactory<string, Modifier>
|
||||
{
|
||||
public static readonly ModifierFactory Instance = new ModifierFactory();
|
||||
|
||||
public Modifier Create(Context cx, ModifierKey init) => new Modifier(cx, init);
|
||||
public Modifier Create(Context cx, string init) => new Modifier(cx, init);
|
||||
}
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write(";namespace");
|
||||
}
|
||||
|
||||
public static Namespace Create(Context cx, INamespaceSymbol ns) => NamespaceFactory.Instance.CreateEntity2(cx, ns);
|
||||
public static Namespace Create(Context cx, INamespaceSymbol ns) => NamespaceFactory.Instance.CreateEntityFromSymbol(cx, ns);
|
||||
|
||||
class NamespaceFactory : ICachedEntityFactory<INamespaceSymbol, Namespace>
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
ExtractCompilerGenerated(trapFile);
|
||||
}
|
||||
|
||||
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method);
|
||||
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method);
|
||||
|
||||
class OrdinaryMethodFactory : ICachedEntityFactory<IMethodSymbol, OrdinaryMethod>
|
||||
{
|
||||
|
||||
@@ -66,10 +66,10 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter original = null) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, parent, original);
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, parent, original));
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, null, null);
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, null, null));
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
@@ -202,7 +202,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return obj != null && obj.GetType() == typeof(VarargsType);
|
||||
}
|
||||
|
||||
public static VarargsType Create(Context cx) => VarargsTypeFactory.Instance.CreateNullableEntity(cx, null);
|
||||
public static VarargsType Create(Context cx) => VarargsTypeFactory.Instance.CreateEntity(cx, typeof(VarargsType), null);
|
||||
|
||||
class VarargsTypeFactory : ICachedEntityFactory<string, VarargsType>
|
||||
{
|
||||
@@ -237,7 +237,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return obj != null && obj.GetType() == typeof(VarargsParam);
|
||||
}
|
||||
|
||||
public static VarargsParam Create(Context cx, Method method) => VarargsParamFactory.Instance.CreateEntity(cx, method);
|
||||
public static VarargsParam Create(Context cx, Method method) => VarargsParamFactory.Instance.CreateEntity(cx, typeof(VarargsParam), method);
|
||||
|
||||
class VarargsParamFactory : ICachedEntityFactory<Method, VarargsParam>
|
||||
{
|
||||
@@ -264,19 +264,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.param_location(this, Original.Location);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => symbol.GetHashCode() + 31 * ConstructedType.GetHashCode();
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as ConstructedExtensionParameter;
|
||||
if (other == null || other.GetType() != typeof(ConstructedExtensionParameter))
|
||||
return false;
|
||||
|
||||
return SymbolEqualityComparer.Default.Equals(symbol, other.symbol) && SymbolEqualityComparer.Default.Equals(ConstructedType, other.ConstructedType);
|
||||
}
|
||||
|
||||
public static ConstructedExtensionParameter Create(Context cx, Method method, Parameter parameter) =>
|
||||
ExtensionParamFactory.Instance.CreateEntity(cx, (method, parameter));
|
||||
ExtensionParamFactory.Instance.CreateEntity(cx, (new SymbolEqualityWrapper(parameter.symbol), new SymbolEqualityWrapper(method.symbol.ReceiverType)), (method, parameter));
|
||||
|
||||
class ExtensionParamFactory : ICachedEntityFactory<(Method, Parameter), ConstructedExtensionParameter>
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.CSharp.Entities.Expressions;
|
||||
@@ -11,10 +12,18 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
class Property : CachedSymbol<IPropertySymbol>, IExpressionParentEntity
|
||||
{
|
||||
protected Property(Context cx, IPropertySymbol init)
|
||||
: base(cx, init) { }
|
||||
: base(cx, init)
|
||||
{
|
||||
type = new Lazy<Type>(() => Type.Create(Context, symbol.Type));
|
||||
}
|
||||
|
||||
readonly Lazy<Type> type;
|
||||
Type Type => type.Value;
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
trapFile.WriteSubId(Type);
|
||||
trapFile.Write(" ");
|
||||
trapFile.WriteSubId(ContainingType);
|
||||
trapFile.Write('.');
|
||||
Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations);
|
||||
@@ -31,7 +40,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
PopulateNullability(trapFile, symbol.GetAnnotatedType());
|
||||
PopulateRefKind(trapFile, symbol.RefKind);
|
||||
|
||||
var type = Type.Create(Context, symbol.Type);
|
||||
var type = Type;
|
||||
trapFile.properties(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition));
|
||||
|
||||
var getter = symbol.GetMethod;
|
||||
@@ -113,7 +122,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
bool isIndexer = prop.IsIndexer || prop.Parameters.Any();
|
||||
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop);
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
}
|
||||
|
||||
public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write(";type");
|
||||
}
|
||||
|
||||
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType>
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
DynamicType(Context cx, IDynamicTypeSymbol init)
|
||||
: base(cx, init) { }
|
||||
|
||||
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
typeArgumentsLazy = new Lazy<Type[]>(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray());
|
||||
}
|
||||
|
||||
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error;
|
||||
|
||||
@@ -29,7 +29,8 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return;
|
||||
}
|
||||
|
||||
trapFile.typeref_type((NamedTypeRef)TypeRef, this);
|
||||
if (UsesTypeRef)
|
||||
trapFile.typeref_type((NamedTypeRef)TypeRef, this);
|
||||
|
||||
if (symbol.IsGenericType)
|
||||
{
|
||||
@@ -106,10 +107,25 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => GetLocations(symbol).FirstOrDefault();
|
||||
|
||||
bool IsAnonymousType() => symbol.IsAnonymousType || symbol.Name.Contains("__AnonymousType");
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
|
||||
trapFile.Write(";type");
|
||||
if (IsAnonymousType())
|
||||
trapFile.Write('*');
|
||||
else
|
||||
{
|
||||
symbol.BuildTypeId(Context, trapFile, symbol);
|
||||
trapFile.Write(";type");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteQuotedId(TextWriter trapFile)
|
||||
{
|
||||
if (IsAnonymousType())
|
||||
trapFile.Write('*');
|
||||
else
|
||||
base.WriteQuotedId(trapFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -148,7 +164,13 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init);
|
||||
}
|
||||
|
||||
public override Type TypeRef => NamedTypeRef.Create(Context, symbol);
|
||||
// Do not create typerefs of constructed generics as they are always in the current trap file.
|
||||
// Create typerefs for constructed error types in case they are fully defined elsewhere.
|
||||
// We cannot use `!this.NeedsPopulation` because this would not be stable as it would depend on
|
||||
// the assembly that was being extracted at the time.
|
||||
bool UsesTypeRef => symbol.TypeKind == TypeKind.Error || SymbolEqualityComparer.Default.Equals(symbol.OriginalDefinition, symbol);
|
||||
|
||||
public override Type TypeRef => UsesTypeRef ? (Type)NamedTypeRef.Create(Context, symbol) : this;
|
||||
}
|
||||
|
||||
class NamedTypeRef : Type<INamedTypeSymbol>
|
||||
@@ -161,7 +183,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public static NamedTypeRef Create(Context cx, INamedTypeSymbol type) =>
|
||||
NamedTypeRefFactory.Instance.CreateEntity2(cx, type);
|
||||
// We need to use a different cache key than `type` to avoid mixing up
|
||||
// `NamedType`s and `NamedTypeRef`s
|
||||
NamedTypeRefFactory.Instance.CreateEntity(cx, (typeof(NamedTypeRef), new SymbolEqualityWrapper(type)), type);
|
||||
|
||||
class NamedTypeRefFactory : ICachedEntityFactory<INamedTypeSymbol, NamedTypeRef>
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return obj != null && obj.GetType() == typeof(NullType);
|
||||
}
|
||||
|
||||
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateNullableEntity(cx, null), NullableAnnotation.None);
|
||||
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, typeof(NullType), null), NullableAnnotation.None);
|
||||
|
||||
class NullTypeFactory : ICachedEntityFactory<ITypeSymbol, NullType>
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
symbol.WriteId(trapFile);
|
||||
}
|
||||
|
||||
public static NullabilityEntity Create(Context cx, Nullability init) => NullabilityFactory.Instance.CreateEntity(cx, init);
|
||||
public static NullabilityEntity Create(Context cx, Nullability init) => NullabilityFactory.Instance.CreateEntity(cx, init, init);
|
||||
|
||||
class NullabilityFactory : ICachedEntityFactory<Nullability, NullabilityEntity>
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public Type PointedAtType { get; private set; }
|
||||
|
||||
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class PointerTypeFactory : ICachedEntityFactory<IPointerTypeSymbol, PointerType>
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
/// </summary>
|
||||
class TupleType : Type<INamedTypeSymbol>
|
||||
{
|
||||
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType>
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
|
||||
symbol.BuildTypeId(Context, trapFile, symbol);
|
||||
trapFile.Write(";tuple");
|
||||
}
|
||||
|
||||
|
||||
@@ -100,19 +100,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
// Visit base types
|
||||
var baseTypes = new List<Type>();
|
||||
if (symbol.BaseType != null)
|
||||
if (symbol.GetNonObjectBaseType(Context) is INamedTypeSymbol @base)
|
||||
{
|
||||
Type baseKey = Create(Context, symbol.BaseType);
|
||||
Type baseKey = Create(Context, @base);
|
||||
trapFile.extend(this, baseKey.TypeRef);
|
||||
if (symbol.TypeKind != TypeKind.Struct)
|
||||
baseTypes.Add(baseKey);
|
||||
}
|
||||
|
||||
if (symbol.TypeKind == TypeKind.Interface)
|
||||
{
|
||||
trapFile.extend(this, Create(Context, Context.Compilation.ObjectType));
|
||||
}
|
||||
|
||||
if (!(base.symbol is IArrayTypeSymbol))
|
||||
{
|
||||
foreach (var t in base.symbol.Interfaces.Select(i => Create(Context, i)))
|
||||
@@ -298,7 +293,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
: base(cx, init, parent, original) { }
|
||||
|
||||
new public static DelegateTypeParameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter original = null) =>
|
||||
DelegateTypeParameterFactory.Instance.CreateEntity(cx, (param, parent, original));
|
||||
// We need to use a different cache key than `param` to avoid mixing up
|
||||
// `DelegateTypeParameter`s and `Parameter`s
|
||||
DelegateTypeParameterFactory.Instance.CreateEntity(cx, (typeof(DelegateTypeParameter), new SymbolEqualityWrapper(param)), (param, parent, original));
|
||||
|
||||
class DelegateTypeParameterFactory : ICachedEntityFactory<(IParameterSymbol, IEntity, Parameter), DelegateTypeParameter>
|
||||
{
|
||||
@@ -324,6 +321,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as Type;
|
||||
return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol);
|
||||
}
|
||||
|
||||
abstract class Type<T> : Type where T : ITypeSymbol
|
||||
|
||||
@@ -38,17 +38,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (symbol.HasUnmanagedTypeConstraint)
|
||||
trapFile.general_type_parameter_constraints(constraints, 4);
|
||||
|
||||
ITypeSymbol baseType = symbol.HasValueTypeConstraint ?
|
||||
Context.Compilation.GetTypeByMetadataName(valueTypeName) :
|
||||
Context.Compilation.ObjectType;
|
||||
|
||||
if (symbol.ReferenceTypeConstraintNullableAnnotation == NullableAnnotation.Annotated)
|
||||
trapFile.general_type_parameter_constraints(constraints, 5);
|
||||
|
||||
foreach (var abase in symbol.GetAnnotatedTypeConstraints())
|
||||
{
|
||||
if (abase.Symbol.TypeKind != TypeKind.Interface)
|
||||
baseType = abase.Symbol;
|
||||
var t = Create(Context, abase.Symbol);
|
||||
trapFile.specific_type_parameter_constraints(constraints, t.TypeRef);
|
||||
if (!abase.HasObliviousNullability())
|
||||
@@ -56,7 +50,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
trapFile.types(this, Kinds.TypeKind.TYPE_PARAMETER, symbol.Name);
|
||||
trapFile.extend(this, Create(Context, baseType).TypeRef);
|
||||
|
||||
Namespace parentNs = Namespace.Create(Context, symbol.TypeParameterKind == TypeParameterKind.Method ? Context.Compilation.GlobalNamespace : symbol.ContainingNamespace);
|
||||
trapFile.parent_namespace(this, parentNs);
|
||||
@@ -88,7 +81,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
static public TypeParameter Create(Context cx, ITypeParameterSymbol p) =>
|
||||
TypeParameterFactory.Instance.CreateEntity(cx, p);
|
||||
TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p);
|
||||
|
||||
/// <summary>
|
||||
/// The variance of this type parameter.
|
||||
|
||||
@@ -49,13 +49,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type.
|
||||
trapFile.Write(' ');
|
||||
BuildMethodId(this, trapFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For some reason, some operators are missing from the Roslyn database of mscorlib.
|
||||
/// This method returns <code>true</code> for such operators.
|
||||
@@ -68,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (containingType != null)
|
||||
{
|
||||
var containingNamedType = containingType as INamedTypeSymbol;
|
||||
return containingNamedType == null || !containingNamedType.MemberNames.Contains(symbol.Name);
|
||||
return containingNamedType == null || !containingNamedType.GetMembers(symbol.Name).Contains(symbol);
|
||||
}
|
||||
|
||||
var pointerType = symbol.Parameters.Select(p => p.Type).OfType<IPointerTypeSymbol>().FirstOrDefault();
|
||||
@@ -190,7 +183,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return result;
|
||||
}
|
||||
|
||||
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol);
|
||||
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class UserOperatorFactory : ICachedEntityFactory<IMethodSymbol, UserOperator>
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Semmle.Extraction.CSharp
|
||||
return ExitCode.Ok;
|
||||
}
|
||||
|
||||
using (var analyser = new Analyser(new LogProgressMonitor(logger), logger))
|
||||
using (var analyser = new Analyser(new LogProgressMonitor(logger), logger, commandLineArguments.AssemblySensitiveTrap))
|
||||
using (var references = new BlockingCollection<MetadataReference>())
|
||||
{
|
||||
try
|
||||
@@ -318,7 +318,7 @@ namespace Semmle.Extraction.CSharp
|
||||
ILogger logger,
|
||||
CommonOptions options)
|
||||
{
|
||||
using (var analyser = new Analyser(pm, logger))
|
||||
using (var analyser = new Analyser(pm, logger, false))
|
||||
using (var references = new BlockingCollection<MetadataReference>())
|
||||
{
|
||||
try
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace Semmle.Extraction.CSharp
|
||||
/// </summary>
|
||||
public bool ClrTracer = false;
|
||||
|
||||
/// <summary>
|
||||
/// Holds if assembly information should be prefixed to TRAP labels.
|
||||
/// </summary>
|
||||
public bool AssemblySensitiveTrap = false;
|
||||
|
||||
public static Options CreateWithEnvironment(string[] arguments)
|
||||
{
|
||||
var options = new Options();
|
||||
@@ -75,6 +80,9 @@ namespace Semmle.Extraction.CSharp
|
||||
case "clrtracer":
|
||||
ClrTracer = value;
|
||||
return true;
|
||||
case "assemblysensitivetrap":
|
||||
AssemblySensitiveTrap = value;
|
||||
return true;
|
||||
default:
|
||||
return base.handleFlag(flag, value);
|
||||
}
|
||||
|
||||
@@ -85,41 +85,62 @@ namespace Semmle.Extraction.CSharp
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds if this type symbol contains a type parameter from the
|
||||
/// declaring generic <paramref name="declaringGeneric"/>.
|
||||
/// Holds if the ID generated for `dependant` will contain a reference to
|
||||
/// the ID for `symbol`. If this is the case, then the ID for `symbol` must
|
||||
/// not contain a reference back to `dependant`.
|
||||
/// </summary>
|
||||
public static bool ContainsTypeParameters(this ITypeSymbol type, Context cx, ISymbol declaringGeneric)
|
||||
public static bool IdDependsOn(this ITypeSymbol dependant, Context cx, ISymbol symbol)
|
||||
{
|
||||
using (cx.StackGuard)
|
||||
var seen = new HashSet<ITypeSymbol>(SymbolEqualityComparer.Default);
|
||||
|
||||
bool IdDependsOnImpl(ITypeSymbol type)
|
||||
{
|
||||
switch (type.TypeKind)
|
||||
if (SymbolEqualityComparer.Default.Equals(type, symbol))
|
||||
return true;
|
||||
|
||||
if (type is null || seen.Contains(type))
|
||||
return false;
|
||||
|
||||
seen.Add(type);
|
||||
|
||||
using (cx.StackGuard)
|
||||
{
|
||||
case TypeKind.Array:
|
||||
var array = (IArrayTypeSymbol)type;
|
||||
return array.ElementType.ContainsTypeParameters(cx, declaringGeneric);
|
||||
case TypeKind.Class:
|
||||
case TypeKind.Interface:
|
||||
case TypeKind.Struct:
|
||||
case TypeKind.Enum:
|
||||
case TypeKind.Delegate:
|
||||
case TypeKind.Error:
|
||||
var named = (INamedTypeSymbol)type;
|
||||
if (named.IsTupleType)
|
||||
named = named.TupleUnderlyingType;
|
||||
if (named.ContainingType != null && named.ContainingType.ContainsTypeParameters(cx, declaringGeneric))
|
||||
return true;
|
||||
return named.TypeArguments.Any(arg => arg.ContainsTypeParameters(cx, declaringGeneric));
|
||||
case TypeKind.Pointer:
|
||||
var ptr = (IPointerTypeSymbol)type;
|
||||
return ptr.PointedAtType.ContainsTypeParameters(cx, declaringGeneric);
|
||||
case TypeKind.TypeParameter:
|
||||
var tp = (ITypeParameterSymbol)type;
|
||||
var declaringGen = tp.TypeParameterKind == TypeParameterKind.Method ? tp.DeclaringMethod : (ISymbol)tp.DeclaringType;
|
||||
return SymbolEqualityComparer.Default.Equals(declaringGen, declaringGeneric);
|
||||
default:
|
||||
return false;
|
||||
switch (type.TypeKind)
|
||||
{
|
||||
case TypeKind.Array:
|
||||
var array = (IArrayTypeSymbol)type;
|
||||
return IdDependsOnImpl(array.ElementType);
|
||||
case TypeKind.Class:
|
||||
case TypeKind.Interface:
|
||||
case TypeKind.Struct:
|
||||
case TypeKind.Enum:
|
||||
case TypeKind.Delegate:
|
||||
case TypeKind.Error:
|
||||
var named = (INamedTypeSymbol)type;
|
||||
if (named.IsTupleType)
|
||||
named = named.TupleUnderlyingType;
|
||||
if (IdDependsOnImpl(named.ContainingType))
|
||||
return true;
|
||||
if (IdDependsOnImpl(named.GetNonObjectBaseType(cx)))
|
||||
return true;
|
||||
if (IdDependsOnImpl(named.ConstructedFrom))
|
||||
return true;
|
||||
return named.TypeArguments.Any(IdDependsOnImpl);
|
||||
case TypeKind.Pointer:
|
||||
var ptr = (IPointerTypeSymbol)type;
|
||||
return IdDependsOnImpl(ptr.PointedAtType);
|
||||
case TypeKind.TypeParameter:
|
||||
var tp = (ITypeParameterSymbol)type;
|
||||
return tp.ContainingSymbol is ITypeSymbol cont
|
||||
? IdDependsOnImpl(cont)
|
||||
: SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbol);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IdDependsOnImpl(dependant);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,27 +151,19 @@ namespace Semmle.Extraction.CSharp
|
||||
/// </summary>
|
||||
/// <param name="cx">The extraction context.</param>
|
||||
/// <param name="trapFile">The trap builder used to store the result.</param>
|
||||
/// <param name="subTermAction">The action to apply to syntactic sub terms of this type.</param>
|
||||
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
|
||||
{
|
||||
if (type.SpecialType != SpecialType.None)
|
||||
{
|
||||
/*
|
||||
* Use the keyword ("int" etc) for the built-in types.
|
||||
* This makes the IDs shorter and means that all built-in types map to
|
||||
* the same entities (even when using multiple versions of mscorlib).
|
||||
*/
|
||||
trapFile.Write(type.ToDisplayString());
|
||||
return;
|
||||
}
|
||||
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
|
||||
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) =>
|
||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, true);
|
||||
|
||||
static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass)
|
||||
{
|
||||
using (cx.StackGuard)
|
||||
{
|
||||
switch (type.TypeKind)
|
||||
{
|
||||
case TypeKind.Array:
|
||||
var array = (IArrayTypeSymbol)type;
|
||||
subTermAction(cx, trapFile, array.ElementType);
|
||||
array.ElementType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
array.BuildArraySuffix(trapFile);
|
||||
return;
|
||||
case TypeKind.Class:
|
||||
@@ -160,15 +173,17 @@ namespace Semmle.Extraction.CSharp
|
||||
case TypeKind.Delegate:
|
||||
case TypeKind.Error:
|
||||
var named = (INamedTypeSymbol)type;
|
||||
named.BuildNamedTypeId(cx, trapFile, subTermAction);
|
||||
named.BuildNamedTypeId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
return;
|
||||
case TypeKind.Pointer:
|
||||
var ptr = (IPointerTypeSymbol)type;
|
||||
subTermAction(cx, trapFile, ptr.PointedAtType);
|
||||
ptr.PointedAtType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
trapFile.Write('*');
|
||||
return;
|
||||
case TypeKind.TypeParameter:
|
||||
var tp = (ITypeParameterSymbol)type;
|
||||
tp.ContainingSymbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
trapFile.Write('_');
|
||||
trapFile.Write(tp.Name);
|
||||
return;
|
||||
case TypeKind.Dynamic:
|
||||
@@ -180,6 +195,42 @@ namespace Semmle.Extraction.CSharp
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildOrWriteId(this ISymbol symbol, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined, bool addBaseClass)
|
||||
{
|
||||
// We need to keep track of the symbol being defined in order to avoid cyclic labels.
|
||||
// For example, in
|
||||
//
|
||||
// ```csharp
|
||||
// class C<T> : IEnumerable<T> { }
|
||||
// ```
|
||||
//
|
||||
// when we generate the label for ``C`1``, the base class `IEnumerable<T>` has `T` as a type
|
||||
// argument, which will be qualified with `__self__` instead of the label we are defining.
|
||||
// In effect, the label will (simplified) look like
|
||||
//
|
||||
// ```
|
||||
// #123 = @"C`1 : IEnumerable<__self___T>"
|
||||
// ```
|
||||
if (SymbolEqualityComparer.Default.Equals(symbol, symbolBeingDefined))
|
||||
trapFile.Write("__self__");
|
||||
else if (symbol is ITypeSymbol type && type.IdDependsOn(cx, symbolBeingDefined))
|
||||
type.BuildTypeId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
else
|
||||
trapFile.WriteSubId(CreateEntity(cx, symbol));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an appropriate ID to the trap builder <paramref name="trapFile"/>
|
||||
/// for the symbol <paramref name="symbol"/> belonging to
|
||||
/// <paramref name="symbolBeingDefined"/>.
|
||||
///
|
||||
/// This will either write a reference to the ID of the entity belonging to
|
||||
/// <paramref name="symbol"/> (`{#label}`), or if that will lead to cyclic IDs,
|
||||
/// it will generate an appropriate ID that encodes the signature of
|
||||
/// <paramref name="symbol" />.
|
||||
/// </summary>
|
||||
public static void BuildOrWriteId(this ISymbol symbol, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined) =>
|
||||
symbol.BuildOrWriteId(cx, trapFile, symbolBeingDefined, true);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an array suffix string for this array type symbol.
|
||||
@@ -211,11 +262,8 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.Write("::");
|
||||
}
|
||||
|
||||
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, ISymbol symbolBeingDefined, bool addBaseClass)
|
||||
{
|
||||
bool prefixAssembly = true;
|
||||
if (named.ContainingAssembly is null) prefixAssembly = false;
|
||||
|
||||
if (named.IsTupleType)
|
||||
{
|
||||
trapFile.Write('(');
|
||||
@@ -224,48 +272,71 @@ namespace Semmle.Extraction.CSharp
|
||||
{
|
||||
trapFile.Write(f.Name);
|
||||
trapFile.Write(":");
|
||||
subTermAction(cx, tb0, f.Type);
|
||||
f.Type.BuildOrWriteId(cx, tb0, symbolBeingDefined, addBaseClass);
|
||||
}
|
||||
);
|
||||
trapFile.Write(")");
|
||||
return;
|
||||
}
|
||||
|
||||
if (named.ContainingType != null)
|
||||
void AddContaining()
|
||||
{
|
||||
subTermAction(cx, trapFile, named.ContainingType);
|
||||
trapFile.Write('.');
|
||||
}
|
||||
else if (named.ContainingNamespace != null)
|
||||
{
|
||||
if (prefixAssembly)
|
||||
BuildAssembly(named.ContainingAssembly, trapFile);
|
||||
named.ContainingNamespace.BuildNamespace(cx, trapFile);
|
||||
if (named.ContainingType != null)
|
||||
{
|
||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
trapFile.Write('.');
|
||||
}
|
||||
else if (named.ContainingNamespace != null)
|
||||
{
|
||||
if (cx.ShouldAddAssemblyTrapPrefix && named.ContainingAssembly is object)
|
||||
BuildAssembly(named.ContainingAssembly, trapFile);
|
||||
named.ContainingNamespace.BuildNamespace(cx, trapFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (named.IsAnonymousType)
|
||||
named.BuildAnonymousName(cx, trapFile, subTermAction, true);
|
||||
else if (named.TypeParameters.IsEmpty)
|
||||
trapFile.Write(named.Name);
|
||||
else if (IsReallyUnbound(named))
|
||||
if (named.TypeParameters.IsEmpty)
|
||||
{
|
||||
AddContaining();
|
||||
trapFile.Write(named.Name);
|
||||
}
|
||||
else if (named.IsReallyUnbound())
|
||||
{
|
||||
AddContaining();
|
||||
trapFile.Write(named.Name);
|
||||
trapFile.Write("`");
|
||||
trapFile.Write(named.TypeParameters.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
subTermAction(cx, trapFile, named.ConstructedFrom);
|
||||
named.ConstructedFrom.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass);
|
||||
trapFile.Write('<');
|
||||
// Encode the nullability of the type arguments in the label.
|
||||
// Type arguments with different nullability can result in
|
||||
// a constructed type with different nullability of its members and methods,
|
||||
// so we need to create a distinct database entity for it.
|
||||
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
|
||||
(ta, tb0) => subTermAction(cx, tb0, ta.Symbol)
|
||||
(ta, tb0) => ta.Symbol.BuildOrWriteId(cx, tb0, symbolBeingDefined, addBaseClass)
|
||||
);
|
||||
trapFile.Write('>');
|
||||
}
|
||||
|
||||
if (addBaseClass && named.GetNonObjectBaseType(cx) is INamedTypeSymbol @base)
|
||||
{
|
||||
// We need to limit unfolding of base classes. For example, in
|
||||
//
|
||||
// ```csharp
|
||||
// class C1<T> { }
|
||||
// class C2<T> : C1<C3<T>> { }
|
||||
// class C3<T> : C1<C2<T>> { }
|
||||
// class C4 : C3<C4> { }
|
||||
// ```
|
||||
//
|
||||
// when we generate the label for `C4`, the base class `C3<C4>` has itself `C1<C2<C4>>` as
|
||||
// a base class, which in turn has `C1<C3<C4>>` as a base class. The latter has the original
|
||||
// base class `C3<C4>` as a type argument, which would lead to infinite unfolding.
|
||||
trapFile.Write(" : ");
|
||||
@base.BuildOrWriteId(cx, trapFile, symbolBeingDefined, addBaseClass: false);
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trapFile)
|
||||
@@ -274,22 +345,14 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.Write('.');
|
||||
}
|
||||
|
||||
static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction, bool includeParamName)
|
||||
static void BuildAnonymousName(this INamedTypeSymbol type, Context cx, TextWriter trapFile)
|
||||
{
|
||||
var buildParam = includeParamName
|
||||
? (prop, tb0) =>
|
||||
{
|
||||
tb0.Write(prop.Name);
|
||||
tb0.Write(' ');
|
||||
subTermAction(cx, tb0, prop.Type);
|
||||
}
|
||||
: (Action<IPropertySymbol, TextWriter>)((prop, tb0) => subTermAction(cx, tb0, prop.Type));
|
||||
int memberCount = type.GetMembers().OfType<IPropertySymbol>().Count();
|
||||
int hackTypeNumber = memberCount == 1 ? 1 : 0;
|
||||
trapFile.Write("<>__AnonType");
|
||||
trapFile.Write(hackTypeNumber);
|
||||
trapFile.Write('<');
|
||||
trapFile.BuildList(",", type.GetMembers().OfType<IPropertySymbol>(), buildParam);
|
||||
trapFile.BuildList(",", type.GetMembers().OfType<IPropertySymbol>(), (prop, tb0) => BuildDisplayName(prop.Type, cx, tb0));
|
||||
trapFile.Write('>');
|
||||
}
|
||||
|
||||
@@ -354,11 +417,9 @@ namespace Semmle.Extraction.CSharp
|
||||
}
|
||||
|
||||
if (namedType.IsAnonymousType)
|
||||
{
|
||||
namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false);
|
||||
}
|
||||
|
||||
trapFile.Write(namedType.Name);
|
||||
namedType.BuildAnonymousName(cx, trapFile);
|
||||
else
|
||||
trapFile.Write(namedType.Name);
|
||||
if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any())
|
||||
{
|
||||
trapFile.Write('<');
|
||||
@@ -434,6 +495,13 @@ namespace Semmle.Extraction.CSharp
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base type of `symbol`. Unlike `symbol.BaseType`, this excludes effective base
|
||||
/// types of type parameters as well as `object` base types.
|
||||
/// </summary>
|
||||
public static INamedTypeSymbol GetNonObjectBaseType(this ITypeSymbol symbol, Context cx) =>
|
||||
symbol is ITypeParameterSymbol || SymbolEqualityComparer.Default.Equals(symbol.BaseType, cx.Compilation.ObjectType) ? null : symbol.BaseType;
|
||||
|
||||
public static IEntity CreateEntity(this Context cx, ISymbol symbol)
|
||||
{
|
||||
if (symbol == null) return null;
|
||||
|
||||
@@ -41,43 +41,13 @@ namespace Semmle.Extraction
|
||||
/// </summary>
|
||||
public readonly TrapWriter TrapWriter;
|
||||
|
||||
/// <summary>
|
||||
/// Holds if assembly information should be prefixed to TRAP labels.
|
||||
/// </summary>
|
||||
public readonly bool ShouldAddAssemblyTrapPrefix;
|
||||
|
||||
int GetNewId() => TrapWriter.IdCounter++;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new entity using the factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">The entity factory.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
public Entity CreateEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity where Type : struct
|
||||
{
|
||||
return CreateNonNullEntity(factory, init);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new entity using the factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">The entity factory.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
public Entity CreateNullableEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity
|
||||
{
|
||||
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new entity using the factory.
|
||||
/// </summary>
|
||||
/// <param name="factory">The entity factory.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
public Entity CreateEntityFromSymbol<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init)
|
||||
where Entity : ICachedEntity
|
||||
where Type : ISymbol
|
||||
{
|
||||
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init);
|
||||
}
|
||||
|
||||
// A recursion guard against writing to the trap file whilst writing an id to the trap file.
|
||||
bool WritingLabel = false;
|
||||
|
||||
@@ -102,47 +72,6 @@ namespace Semmle.Extraction
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new entity using the factory.
|
||||
/// Uses a different cache to <see cref="CreateEntity{Type, Entity}(ICachedEntityFactory{Type, Entity}, Type)"/>,
|
||||
/// and can store null values.
|
||||
/// </summary>
|
||||
/// <param name="factory">The entity factory.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
public Entity CreateEntity2<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity
|
||||
{
|
||||
using (StackGuard)
|
||||
{
|
||||
var entity = factory.Create(this, init);
|
||||
|
||||
if (entityLabelCache.TryGetValue(entity, out var label))
|
||||
{
|
||||
entity.Label = label;
|
||||
}
|
||||
else
|
||||
{
|
||||
label = GetNewLabel();
|
||||
entity.Label = label;
|
||||
entityLabelCache[entity] = label;
|
||||
|
||||
DefineLabel(entity, TrapWriter.Writer, Extractor);
|
||||
|
||||
if (entity.NeedsPopulation)
|
||||
Populate(init as ISymbol, entity);
|
||||
#if DEBUG_LABELS
|
||||
using (var id = new StringWriter())
|
||||
{
|
||||
entity.WriteId(id);
|
||||
CheckEntityHasUniqueLabel(id.ToString(), entity);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_LABELS
|
||||
private void CheckEntityHasUniqueLabel(string id, ICachedEntity entity)
|
||||
{
|
||||
@@ -159,12 +88,27 @@ namespace Semmle.Extraction
|
||||
|
||||
public Label GetNewLabel() => new Label(GetNewId());
|
||||
|
||||
public Entity CreateNonNullEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init)
|
||||
public Entity CreateEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, object cacheKey, Type init)
|
||||
where Entity : ICachedEntity =>
|
||||
cacheKey is ISymbol s ? CreateEntity(factory, s, init, symbolEntityCache) : CreateEntity(factory, cacheKey, init, objectEntityCache);
|
||||
|
||||
public Entity CreateEntityFromSymbol<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init)
|
||||
where Type : ISymbol
|
||||
where Entity : ICachedEntity => CreateEntity(factory, init, init, symbolEntityCache);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, or returns the existing one from the cache.
|
||||
/// </summary>
|
||||
/// <param name="factory">The entity factory.</param>
|
||||
/// <param name="cacheKey">The key used for caching.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <param name="dictionary">The dictionary to use for caching.</param>
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
Entity CreateEntity<Type, CacheKeyType, Entity>(ICachedEntityFactory<Type, Entity> factory, CacheKeyType cacheKey, Type init, IDictionary<CacheKeyType, ICachedEntity> dictionary)
|
||||
where CacheKeyType : notnull
|
||||
where Entity : ICachedEntity
|
||||
{
|
||||
if (init is null) throw new ArgumentException("Unexpected null value", nameof(init));
|
||||
|
||||
if (objectEntityCache.TryGetValue(init, out var cached))
|
||||
if (dictionary.TryGetValue(cacheKey, out var cached))
|
||||
return (Entity)cached;
|
||||
|
||||
using (StackGuard)
|
||||
@@ -173,7 +117,7 @@ namespace Semmle.Extraction
|
||||
var entity = factory.Create(this, init);
|
||||
entity.Label = label;
|
||||
|
||||
objectEntityCache[init] = entity;
|
||||
dictionary[cacheKey] = entity;
|
||||
|
||||
DefineLabel(entity, TrapWriter.Writer, Extractor);
|
||||
if (entity.NeedsPopulation)
|
||||
@@ -227,8 +171,9 @@ namespace Semmle.Extraction
|
||||
#if DEBUG_LABELS
|
||||
readonly Dictionary<string, ICachedEntity> idLabelCache = new Dictionary<string, ICachedEntity>();
|
||||
#endif
|
||||
readonly Dictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
|
||||
readonly Dictionary<ICachedEntity, Label> entityLabelCache = new Dictionary<ICachedEntity, Label>();
|
||||
|
||||
readonly IDictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
|
||||
readonly IDictionary<ISymbol, ICachedEntity> symbolEntityCache = new Dictionary<ISymbol, ICachedEntity>(10000, SymbolEqualityComparer.IncludeNullability);
|
||||
readonly HashSet<Label> extractedGenerics = new HashSet<Label>();
|
||||
|
||||
/// <summary>
|
||||
@@ -289,12 +234,14 @@ namespace Semmle.Extraction
|
||||
/// <param name="c">The Roslyn compilation.</param>
|
||||
/// <param name="extractedEntity">Name of the source/dll file.</param>
|
||||
/// <param name="scope">Defines which symbols are included in the trap file (e.g. AssemblyScope or SourceScope)</param>
|
||||
public Context(IExtractor e, Compilation c, TrapWriter trapWriter, IExtractionScope scope)
|
||||
/// <param name="addAssemblyTrapPrefix">Whether to add assembly prefixes to TRAP labels.</param>
|
||||
public Context(IExtractor e, Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix)
|
||||
{
|
||||
Extractor = e;
|
||||
Compilation = c;
|
||||
Scope = scope;
|
||||
TrapWriter = trapWriter;
|
||||
ShouldAddAssemblyTrapPrefix = addAssemblyTrapPrefix;
|
||||
}
|
||||
|
||||
public bool FromSource => Scope.FromSource;
|
||||
@@ -423,8 +370,8 @@ namespace Semmle.Extraction
|
||||
throw new InternalError("Unexpected TrapStackBehaviour");
|
||||
}
|
||||
|
||||
var a = duplicationGuard ?
|
||||
(Action)(() => WithDuplicationGuard(new Key(entity, this.Create(entity.ReportingLocation)), () => entity.Populate(TrapWriter.Writer))) :
|
||||
var a = duplicationGuard && this.Create(entity.ReportingLocation) is NonGeneratedSourceLocation loc ?
|
||||
(Action)(() => WithDuplicationGuard(new Key(entity, loc), () => entity.Populate(TrapWriter.Writer))) :
|
||||
(Action)(() => this.Try(null, optionalSymbol, () => entity.Populate(TrapWriter.Writer)));
|
||||
|
||||
if (deferred)
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Semmle.Extraction.Entities
|
||||
return Equals(symbol, other.symbol);
|
||||
}
|
||||
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location? loc) => AssemblyConstructorFactory.Instance.CreateNullableEntity(cx, loc);
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => AssemblyConstructorFactory.Instance.CreateEntity(cx, loc, loc);
|
||||
|
||||
class AssemblyConstructorFactory : ICachedEntityFactory<Microsoft.CodeAnalysis.Location?, Assembly>
|
||||
{
|
||||
@@ -59,11 +59,12 @@ namespace Semmle.Extraction.Entities
|
||||
public Assembly Create(Context cx, Microsoft.CodeAnalysis.Location? init) => new Assembly(cx, init);
|
||||
}
|
||||
|
||||
static readonly object outputAssemblyCacheKey = new object();
|
||||
public static Location CreateOutputAssembly(Context cx)
|
||||
{
|
||||
if (cx.Extractor.OutputPath == null)
|
||||
throw new InternalError("Attempting to create the output assembly in standalone extraction mode");
|
||||
return AssemblyConstructorFactory.Instance.CreateNullableEntity(cx, null);
|
||||
return AssemblyConstructorFactory.Instance.CreateEntity(cx, outputAssemblyCacheKey, null);
|
||||
}
|
||||
|
||||
public override void WriteId(System.IO.TextWriter trapFile)
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace Semmle.Extraction.Entities
|
||||
|
||||
public static string PathAsDatabaseString(string path) => path.Replace('\\', '/');
|
||||
|
||||
public static File Create(Context cx, string path) => FileFactory.Instance.CreateEntity(cx, path);
|
||||
public static File Create(Context cx, string path) => FileFactory.Instance.CreateEntity(cx, (typeof(File), path), path);
|
||||
|
||||
public static File CreateGenerated(Context cx) => GeneratedFile.Create(cx);
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Semmle.Extraction.Entities
|
||||
}
|
||||
|
||||
public static GeneratedFile Create(Context cx) =>
|
||||
GeneratedFileFactory.Instance.CreateNullableEntity(cx, null);
|
||||
GeneratedFileFactory.Instance.CreateEntity(cx, typeof(GeneratedFile), null);
|
||||
|
||||
class GeneratedFileFactory : ICachedEntityFactory<string?, GeneratedFile>
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Semmle.Extraction.Entities
|
||||
}
|
||||
|
||||
public static Folder Create(Context cx, DirectoryInfo folder) =>
|
||||
FolderFactory.Instance.CreateEntity2(cx, folder);
|
||||
FolderFactory.Instance.CreateEntity(cx, folder, folder);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location? ReportingLocation => null;
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Semmle.Extraction.Entities
|
||||
|
||||
public override bool Equals(object? obj) => obj != null && obj.GetType() == typeof(GeneratedLocation);
|
||||
|
||||
public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateNullableEntity(cx, null);
|
||||
public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null);
|
||||
|
||||
class GeneratedLocationFactory : ICachedEntityFactory<string?, GeneratedLocation>
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.Entities
|
||||
FileEntity = File.Create(Context, Position.Path);
|
||||
}
|
||||
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location? loc) => SourceLocationFactory.Instance.CreateNullableEntity(cx, loc);
|
||||
public new static Location Create(Context cx, Microsoft.CodeAnalysis.Location loc) => SourceLocationFactory.Instance.CreateEntity(cx, loc, loc);
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
@@ -55,11 +55,11 @@ namespace Semmle.Extraction.Entities
|
||||
trapFile.Write(Position.Span.End.Character);
|
||||
}
|
||||
|
||||
class SourceLocationFactory : ICachedEntityFactory<Microsoft.CodeAnalysis.Location?, SourceLocation>
|
||||
class SourceLocationFactory : ICachedEntityFactory<Microsoft.CodeAnalysis.Location, SourceLocation>
|
||||
{
|
||||
public static readonly SourceLocationFactory Instance = new SourceLocationFactory();
|
||||
|
||||
public SourceLocation Create(Context cx, Microsoft.CodeAnalysis.Location? init) => new NonGeneratedSourceLocation(cx, init);
|
||||
public SourceLocation Create(Context cx, Microsoft.CodeAnalysis.Location init) => new NonGeneratedSourceLocation(cx, init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,41 +109,33 @@ namespace Semmle.Extraction
|
||||
|
||||
public static class ICachedEntityFactoryExtensions
|
||||
{
|
||||
public static Entity CreateEntity<Entity, T1, T2>(this ICachedEntityFactory<(T1, T2), Entity> factory, Context cx, T1 t1, T2 t2)
|
||||
where Entity : ICachedEntity => factory.CreateEntity2(cx, (t1, t2));
|
||||
|
||||
public static Entity CreateEntity<Entity, T1, T2, T3>(this ICachedEntityFactory<(T1, T2, T3), Entity> factory, Context cx, T1 t1, T2 t2, T3 t3)
|
||||
where Entity : ICachedEntity => factory.CreateEntity2(cx, (t1, t2, t3));
|
||||
|
||||
public static Entity CreateEntity<Entity, T1, T2, T3, T4>(this ICachedEntityFactory<(T1, T2, T3, T4), Entity> factory, Context cx, T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
where Entity : ICachedEntity => factory.CreateEntity2(cx, (t1, t2, t3, t4));
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, or returns the existing one from the cache,
|
||||
/// based on the supplied cache key.
|
||||
/// </summary>
|
||||
/// <typeparam name="Type">The type used to construct the entity.</typeparam>
|
||||
/// <typeparam name="Entity">The type of the entity to create.</typeparam>
|
||||
/// <param name="factory">The factory used to construct the entity.</param>
|
||||
/// <param name="cx">The extractor context.</param>
|
||||
/// <param name="cacheKey">The key used for caching.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The entity.</returns>
|
||||
public static Entity CreateEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, object cacheKey, Type init)
|
||||
where Entity : ICachedEntity => cx.CreateEntity(factory, cacheKey, init);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, or returns the existing one from the cache.
|
||||
/// Creates and populates a new entity from an `ISymbol`, or returns the existing one
|
||||
/// from the cache.
|
||||
/// </summary>
|
||||
/// <typeparam name="Type">The symbol type used to construct the entity.</typeparam>
|
||||
/// <typeparam name="Type">The type used to construct the entity.</typeparam>
|
||||
/// <typeparam name="Entity">The type of the entity to create.</typeparam>
|
||||
/// <param name="cx">The extractor context.</param>
|
||||
/// <param name="factory">The factory used to construct the entity.</param>
|
||||
/// <param name="init">The initializer for the entity, which may not be null.</param>
|
||||
/// <returns>The entity.</returns>
|
||||
public static Entity CreateEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init) where Type : notnull
|
||||
where Entity : ICachedEntity => cx.CreateNonNullEntity(factory, init);
|
||||
|
||||
public static Entity CreateNullableEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
|
||||
where Entity : ICachedEntity => cx.CreateNullableEntity(factory, init);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, but uses a different cache.
|
||||
/// </summary>
|
||||
/// <typeparam name="Type">The symbol type used to construct the entity.</typeparam>
|
||||
/// <typeparam name="Entity">The type of the entity to create.</typeparam>
|
||||
/// <param name="cx">The extractor context.</param>
|
||||
/// <param name="factory">The factory used to construct the entity.</param>
|
||||
/// <param name="init">The initializer for the entity, which may be null.</param>
|
||||
/// <param name="init">The initializer for the entity.</param>
|
||||
/// <returns>The entity.</returns>
|
||||
public static Entity CreateEntity2<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
|
||||
where Entity : ICachedEntity => cx.CreateEntity2(factory, init);
|
||||
public static Entity CreateEntityFromSymbol<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
|
||||
where Type : ISymbol
|
||||
where Entity : ICachedEntity => cx.CreateEntityFromSymbol(factory, init);
|
||||
|
||||
public static void DefineLabel(this IEntity entity, TextWriter trapFile, IExtractor extractor)
|
||||
{
|
||||
@@ -156,7 +148,7 @@ namespace Semmle.Extraction
|
||||
catch (Exception ex) // lgtm[cs/catch-of-all-exceptions]
|
||||
{
|
||||
trapFile.WriteLine("\"");
|
||||
extractor.Message(new Message("Unhandled exception generating id", entity.ToString() ?? "", null, ex.StackTrace));
|
||||
extractor.Message(new Message($"Unhandled exception generating id: {ex.Message}", entity.ToString() ?? "", null, ex.StackTrace));
|
||||
}
|
||||
trapFile.WriteLine();
|
||||
}
|
||||
|
||||
@@ -87,8 +87,9 @@ namespace Semmle.Extraction
|
||||
/// <param name="c">The C# compilation.</param>
|
||||
/// <param name="trapWriter">The trap writer.</param>
|
||||
/// <param name="scope">The extraction scope (what to include in this trap file).</param>
|
||||
/// <param name="addAssemblyTrapPrefix">Whether to add assembly prefixes to TRAP labels.</param>
|
||||
/// <returns></returns>
|
||||
Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope);
|
||||
Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -187,9 +188,9 @@ namespace Semmle.Extraction
|
||||
}
|
||||
}
|
||||
|
||||
public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope)
|
||||
public Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope, bool addAssemblyTrapPrefix)
|
||||
{
|
||||
return new Context(this, c, trapWriter, scope);
|
||||
return new Context(this, c, trapWriter, scope, addAssemblyTrapPrefix);
|
||||
}
|
||||
|
||||
public IEnumerable<string> MissingTypes => missingTypes;
|
||||
|
||||
@@ -69,7 +69,6 @@ namespace Semmle.Extraction
|
||||
}
|
||||
else
|
||||
TrapBuilder.Write(arg.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction
|
||||
{
|
||||
@@ -65,16 +66,6 @@ namespace Semmle.Extraction
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs the given action <paramref name="a"/>, guarding for trap duplication
|
||||
/// based on the ID an location of this entity.
|
||||
/// </summary>
|
||||
protected void WithDuplicationGuard(System.Action a, IEntity location)
|
||||
{
|
||||
var key = new Key(this, location);
|
||||
Context.WithDuplicationGuard(key, a);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => symbol is null ? 0 : symbol.GetHashCode();
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
@@ -85,4 +76,20 @@ namespace Semmle.Extraction
|
||||
|
||||
public abstract TrapStackBehaviour TrapStackBehaviour { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A class used to wrap an `ISymbol` object, which uses `SymbolEqualityComparer.Default`
|
||||
/// for comparison.
|
||||
/// </summary>
|
||||
public sealed class SymbolEqualityWrapper
|
||||
{
|
||||
public ISymbol Symbol { get; }
|
||||
|
||||
public SymbolEqualityWrapper(ISymbol symbol) { Symbol = symbol; }
|
||||
|
||||
public override bool Equals(object? other) =>
|
||||
other is SymbolEqualityWrapper sew && SymbolEqualityComparer.Default.Equals(Symbol, sew.Symbol);
|
||||
|
||||
public override int GetHashCode() => 11 * Symbol.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user