mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge remote-tracking branch 'upstream/master' into promiseAll
This commit is contained in:
@@ -5,7 +5,7 @@ This open source repository contains the standard CodeQL libraries and queries t
|
||||
## How do I learn CodeQL and run queries?
|
||||
|
||||
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open source project that's currently being analyzed.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ The following changes in version 1.23 affect C# analysis in all applications.
|
||||
|
||||
## New queries
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. |
|
||||
|
||||
23
change-notes/1.24/analysis-javascript.md
Normal file
23
change-notes/1.24/analysis-javascript.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Improvements to JavaScript analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
* Support for the following frameworks and libraries has been improved:
|
||||
- [react](https://www.npmjs.com/package/react)
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|---------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
|
||||
| Clear-text logging of sensitive information (`js/clear-text-logging`) | More results | More results involving `process.env` and indirect calls to logging methods are recognized. |
|
||||
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false positive results | This query now recognizes additional cases where a single replacement is likely to be intentional. |
|
||||
| Unbound event handler receiver (`js/unbound-event-handler-receiver`) | Fewer false positive results | This query now recognizes additional ways event handler receivers can be bound. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
@@ -15,7 +15,10 @@ import cpp
|
||||
|
||||
from ExprInVoidContext op
|
||||
where
|
||||
op instanceof EQExpr
|
||||
or
|
||||
op.(FunctionCall).getTarget().hasName("operator==")
|
||||
not op.isUnevaluated() and
|
||||
(
|
||||
op instanceof EQExpr
|
||||
or
|
||||
op.(FunctionCall).getTarget().hasName("operator==")
|
||||
)
|
||||
select op, "This '==' operator has no effect. The assignment ('=') operator was probably intended."
|
||||
|
||||
@@ -84,8 +84,10 @@ where
|
||||
not peivc.getEnclosingFunction().isDefaulted() and
|
||||
not exists(Macro m | peivc = m.getAnInvocation().getAnExpandedElement()) and
|
||||
not peivc.isFromTemplateInstantiation(_) and
|
||||
not peivc.isFromUninstantiatedTemplate(_) and
|
||||
parent = peivc.getParent() and
|
||||
not parent.isInMacroExpansion() and
|
||||
not peivc.isUnevaluated() and
|
||||
not parent instanceof PureExprInVoidContext and
|
||||
not peivc.getEnclosingFunction().isCompilerGenerated() and
|
||||
not peivc.getType() instanceof UnknownType and
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
|
||||
return ptr + a >= ptr_end || ptr + a < ptr; // BAD
|
||||
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
|
||||
return ptr + i >= ptr_end || ptr + i < ptr; // BAD
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
|
||||
return a >= ptr_end - ptr; // GOOD
|
||||
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
|
||||
return i >= ptr_end - ptr; // GOOD
|
||||
}
|
||||
@@ -4,29 +4,27 @@
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
The expression <code>ptr + a < ptr</code> is equivalent to <code>a <
|
||||
0</code>, and an optimizing compiler is likely to make that replacement,
|
||||
thereby removing a range check that might have been necessary for security.
|
||||
If <code>a</code> is known to be non-negative, the compiler can even replace <code>ptr +
|
||||
a < ptr</code> with <code>false</code>.
|
||||
When checking for integer overflow, you may often write tests like
|
||||
<code>p + i < p</code>. This works fine if <code>p</code> and
|
||||
<code>i</code> are unsigned integers, since any overflow in the addition
|
||||
will cause the value to simply "wrap around." However, using this pattern when
|
||||
<code>p</code> is a pointer is problematic because pointer overflow has
|
||||
undefined behavior according to the C and C++ standards. If the addition
|
||||
overflows and has an undefined result, the comparison will likewise be
|
||||
undefined; it may produce an unintended result, or may be deleted entirely by an
|
||||
optimizing compiler.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The reason is that pointer arithmetic overflow in C/C++ is undefined
|
||||
behavior. The optimizing compiler can assume that the program has no
|
||||
undefined behavior, which means that adding a positive number to <code>ptr</code> cannot
|
||||
produce a pointer less than <code>ptr</code>.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
To check whether an index <code>a</code> is less than the length of an array,
|
||||
simply compare these two numbers as unsigned integers: <code>a < ARRAY_LENGTH</code>.
|
||||
To check whether an index <code>i</code> is less than the length of an array,
|
||||
simply compare these two numbers as unsigned integers: <code>i < ARRAY_LENGTH</code>.
|
||||
If the length of the array is defined as the difference between two pointers
|
||||
<code>ptr</code> and <code>p_end</code>, write <code>a < p_end - ptr</code>.
|
||||
If a is <code>signed</code>, cast it to <code>unsigned</code>
|
||||
in order to guard against negative <code>a</code>. For example, write
|
||||
<code>(size_t)a < p_end - ptr</code>.
|
||||
<code>ptr</code> and <code>p_end</code>, write <code>i < p_end - ptr</code>.
|
||||
If <code>i</code> is signed, cast it to unsigned
|
||||
in order to guard against negative <code>i</code>. For example, write
|
||||
<code>(size_t)i < p_end - ptr</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
@@ -43,14 +41,14 @@ overflows and wraps around.
|
||||
<p>
|
||||
In both of these checks, the operations are performed in the wrong order.
|
||||
First, an expression that may cause undefined behavior is evaluated
|
||||
(<code>ptr + a</code>), and then the result is checked for being in range.
|
||||
(<code>ptr + i</code>), and then the result is checked for being in range.
|
||||
But once undefined behavior has happened in the pointer addition, it cannot
|
||||
be recovered from: it's too late to perform the range check after a possible
|
||||
pointer overflow.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
While it's not the subject of this query, the expression <code>ptr + a <
|
||||
While it's not the subject of this query, the expression <code>ptr + i <
|
||||
ptr_end</code> is also an invalid range check. It's undefined behavor in
|
||||
C/C++ to create a pointer that points more than one past the end of an
|
||||
allocation.
|
||||
|
||||
@@ -3,9 +3,20 @@
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols.</p>
|
||||
<p>Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols may expose the software to known vulnerabilities or permit weak encryption algorithms to be used. Disabling the minimum-recommended protocols is also flagged.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>When using the TLS or SSLv23 protocol, set the <code>no_tlsv1</code> and <code>no_tlsv1_1</code> options, but do not set <code>no_tlsv1_2</code>. When using the SSLv23 protocol, also set the <code>no_sslv3</code> option.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the following example, the <code>no_tlsv1_1</code> option has not been set. Use of TLS 1.1 is not recommended.</p>
|
||||
<sample src="TlsSettingsMisconfigurationBad.cpp"/>
|
||||
<p>In the corrected example, the <code>no_tlsv1</code> and <code>no_tlsv1_1</code> options have both been set, ensuring the use of TLS 1.2 or later.</p>
|
||||
<sample src="TlsSettingsMisconfigurationGood.cpp"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
<a href="https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio.html">Boost.Asio documentation</a>.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @name Boost_asio TLS Settings Misconfiguration
|
||||
* @description Using TLS or SSLv23 protool from the boost::asio library, but not disabling deprecated protocols or disabling minimum-recommended protocols
|
||||
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @id cpp/boost/tls_settings_misconfiguration
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
void useTLS_bad()
|
||||
{
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
|
||||
ctx.set_options(boost::asio::ssl::context::no_tlsv1); // BAD: missing no_tlsv1_1
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
void useTLS_good()
|
||||
{
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
|
||||
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -4,13 +4,22 @@
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Using boost::asio library but specifying a deprecated hardcoded protocol.</p>
|
||||
<p>Using a deprecated hardcoded protocol instead of negotiting would lock your application to a protocol that has known vulnerabilities or weaknesses.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Only use modern protocols such as TLS 1.2 or TLS 1.3.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>In the following example, the <code>sslv2</code> protocol is specified. This protocol is out of date and its use is not recommended.</p>
|
||||
<sample src="UseOfDeprecatedHardcodedProtocolBad.cpp"/>
|
||||
<p>In the corrected example, the <code>tlsv13</code> protocol is used instead.</p>
|
||||
<sample src="UseOfDeprecatedHardcodedProtocolGood.cpp"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
<a href="https://www.boost.org/doc/libs/1_71_0/doc/html/boost_asio.html">Boost.Asio documentation</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
void useProtocol_bad()
|
||||
{
|
||||
boost::asio::ssl::context ctx_sslv2(boost::asio::ssl::context::sslv2); // BAD: outdated protocol
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
void useProtocol_good()
|
||||
{
|
||||
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13);
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Conditionally uninitialized variable
|
||||
* @description When an initialization function is used to initialize a local variable, but the
|
||||
* returned status code is not checked, the variable may be left in an uninitialized
|
||||
* @description An initialization function is used to initialize a local variable, but the
|
||||
* returned status code is not checked. The variable may be left in an uninitialized
|
||||
* state, and reading the variable may result in undefined behavior.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
|
||||
@@ -219,7 +219,6 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
node1.asExpr() = a and
|
||||
a.getLValue() = fa
|
||||
) and
|
||||
not fa.getTarget().isStatic() and
|
||||
node2.getPreUpdateNode().asExpr() = fa.getQualifier() and
|
||||
f.(FieldContent).getField() = fa.getTarget()
|
||||
)
|
||||
|
||||
@@ -182,7 +182,7 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode {
|
||||
|
||||
override Type getType() { result = f.getDeclaringType() }
|
||||
|
||||
override string toString() { result = "`this` parameter in " + f.getName() }
|
||||
override string toString() { result = "this" }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
|
||||
|
||||
@@ -133,8 +133,7 @@ private module PartialDefinitions {
|
||||
TReferenceArgument(Expr arg, VariableAccess va) { referenceArgument(va, arg) }
|
||||
|
||||
private predicate isInstanceFieldWrite(FieldAccess fa, ControlFlowNode node) {
|
||||
not fa.getTarget().isStatic() and
|
||||
assignmentLikeOperation(node, fa.getTarget(), fa, _)
|
||||
assignmentLikeOperation(node, _, fa, _)
|
||||
}
|
||||
|
||||
class PartialDefinition extends TPartialDefinition {
|
||||
|
||||
@@ -85,7 +85,11 @@ class Node extends TIRDataFlowNode {
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
string toString() { result = instr.toString() }
|
||||
string toString() {
|
||||
// This predicate is overridden in subclasses. This default implementation
|
||||
// does not use `Instruction.toString` because that's expensive to compute.
|
||||
result = this.asInstruction().getOpcode().toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +111,8 @@ class ExprNode extends Node {
|
||||
* expression may be a `Conversion`.
|
||||
*/
|
||||
Expr getConvertedExpr() { result = this.asConvertedExpr() }
|
||||
|
||||
override string toString() { result = this.asConvertedExpr().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,6 +129,14 @@ class ParameterNode extends Node {
|
||||
predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() }
|
||||
|
||||
Parameter getParameter() { result = instr.getParameter() }
|
||||
|
||||
override string toString() { result = instr.getParameter().toString() }
|
||||
}
|
||||
|
||||
private class ThisParameterNode extends Node {
|
||||
override InitializeThisInstruction instr;
|
||||
|
||||
override string toString() { result = "this" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,6 +147,8 @@ class UninitializedNode extends Node {
|
||||
override UninitializedInstruction instr;
|
||||
|
||||
LocalVariable getLocalVariable() { result = instr.getLocalVariable() }
|
||||
|
||||
override string toString() { result = this.getLocalVariable().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
| BarrierGuard.cpp:9:10:9:15 | Load: source | BarrierGuard.cpp:5:19:5:24 | InitializeParameter: source |
|
||||
| BarrierGuard.cpp:15:10:15:15 | Load: source | BarrierGuard.cpp:13:17:13:22 | InitializeParameter: source |
|
||||
| BarrierGuard.cpp:25:10:25:15 | Load: source | BarrierGuard.cpp:21:17:21:22 | InitializeParameter: source |
|
||||
| BarrierGuard.cpp:31:10:31:15 | Load: source | BarrierGuard.cpp:29:16:29:21 | InitializeParameter: source |
|
||||
| BarrierGuard.cpp:33:10:33:15 | Load: source | BarrierGuard.cpp:29:16:29:21 | InitializeParameter: source |
|
||||
| BarrierGuard.cpp:53:13:53:13 | Load: x | BarrierGuard.cpp:49:10:49:15 | Call: call to source |
|
||||
| BarrierGuard.cpp:55:13:55:13 | Load: x | BarrierGuard.cpp:49:10:49:15 | Call: call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source |
|
||||
| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
|
||||
| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 |
|
||||
| clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source |
|
||||
| clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source |
|
||||
| clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source |
|
||||
| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source |
|
||||
| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source |
|
||||
| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:33:18:33:23 | Call: call to source |
|
||||
| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:41:17:41:22 | Call: call to source |
|
||||
| dispatch.cpp:31:16:31:24 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source |
|
||||
| dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source |
|
||||
| dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source |
|
||||
| dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source |
|
||||
| dispatch.cpp:39:15:39:23 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source |
|
||||
| dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source |
|
||||
| dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source |
|
||||
| dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source |
|
||||
| test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:15:8:15:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:26:8:26:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
|
||||
| test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source |
|
||||
| test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source |
|
||||
| test.cpp:58:10:58:10 | Load: t | test.cpp:50:14:50:19 | Call: call to source |
|
||||
| test.cpp:71:8:71:9 | Load: x4 | test.cpp:66:30:66:36 | InitializeParameter: source1 |
|
||||
| test.cpp:76:8:76:9 | Load: u1 | test.cpp:75:7:75:8 | Uninitialized: definition of u1 |
|
||||
| test.cpp:84:8:84:18 | Load: ... ? ... : ... | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
|
||||
| test.cpp:86:8:86:9 | Load: i1 | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
|
||||
| test.cpp:90:8:90:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
|
||||
| test.cpp:92:8:92:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 |
|
||||
| test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source |
|
||||
| test.cpp:140:8:140:8 | Load: y | test.cpp:138:27:138:32 | Call: call to source |
|
||||
| test.cpp:144:8:144:8 | Load: s | test.cpp:151:33:151:38 | Call: call to source |
|
||||
| test.cpp:152:8:152:8 | Load: y | test.cpp:151:33:151:38 | Call: call to source |
|
||||
| test.cpp:157:8:157:8 | Load: x | test.cpp:164:34:164:39 | Call: call to source |
|
||||
| test.cpp:165:8:165:8 | Load: y | test.cpp:164:34:164:39 | Call: call to source |
|
||||
| test.cpp:178:8:178:8 | Load: y | test.cpp:171:11:171:16 | Call: call to source |
|
||||
| test.cpp:260:12:260:12 | Load: x | test.cpp:245:14:245:19 | Call: call to source |
|
||||
| test.cpp:266:12:266:12 | Load: x | test.cpp:265:22:265:27 | Call: call to source |
|
||||
| test.cpp:289:14:289:14 | Load: x | test.cpp:305:17:305:22 | Call: call to source |
|
||||
| test.cpp:318:7:318:7 | Load: x | test.cpp:314:4:314:9 | Call: call to source |
|
||||
| test.cpp:450:9:450:22 | CopyValue: (statement expression) | test.cpp:449:26:449:32 | InitializeParameter: source1 |
|
||||
| test.cpp:461:8:461:12 | Load: local | test.cpp:449:26:449:32 | InitializeParameter: source1 |
|
||||
| true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source |
|
||||
| true_upon_entry.cpp:39:8:39:8 | Load: x | true_upon_entry.cpp:33:11:33:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:49:8:49:8 | Load: x | true_upon_entry.cpp:43:11:43:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:57:8:57:8 | Load: x | true_upon_entry.cpp:54:11:54:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:66:8:66:8 | Load: x | true_upon_entry.cpp:62:11:62:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:78:8:78:8 | Load: x | true_upon_entry.cpp:70:11:70:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:86:8:86:8 | Load: x | true_upon_entry.cpp:83:11:83:16 | Call: call to source |
|
||||
| true_upon_entry.cpp:105:8:105:8 | Load: x | true_upon_entry.cpp:98:11:98:16 | Call: call to source |
|
||||
| BarrierGuard.cpp:9:10:9:15 | source | BarrierGuard.cpp:5:19:5:24 | source |
|
||||
| BarrierGuard.cpp:15:10:15:15 | source | BarrierGuard.cpp:13:17:13:22 | source |
|
||||
| BarrierGuard.cpp:25:10:25:15 | source | BarrierGuard.cpp:21:17:21:22 | source |
|
||||
| BarrierGuard.cpp:31:10:31:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:33:10:33:15 | source | BarrierGuard.cpp:29:16:29:21 | source |
|
||||
| BarrierGuard.cpp:53:13:53:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| BarrierGuard.cpp:55:13:55:13 | x | BarrierGuard.cpp:49:10:49:15 | call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | (int)... | acrossLinkTargets.cpp:19:27:19:32 | call to source |
|
||||
| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source |
|
||||
| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 |
|
||||
| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source |
|
||||
| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source |
|
||||
| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source |
|
||||
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:33:18:33:23 | call to source |
|
||||
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:41:17:41:22 | call to source |
|
||||
| dispatch.cpp:31:16:31:24 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:32:16:32:24 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
|
||||
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| dispatch.cpp:39:15:39:23 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
|
||||
| dispatch.cpp:40:15:40:23 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
|
||||
| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
|
||||
| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
|
||||
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:15:8:15:9 | t2 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:26:8:26:9 | t1 | test.cpp:6:12:6:17 | call to source |
|
||||
| test.cpp:30:8:30:8 | t | test.cpp:35:10:35:15 | call to source |
|
||||
| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source |
|
||||
| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source |
|
||||
| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 |
|
||||
| test.cpp:76:8:76:9 | u1 | test.cpp:75:7:75:8 | u1 |
|
||||
| test.cpp:84:8:84:18 | ... ? ... : ... | test.cpp:83:7:83:8 | u2 |
|
||||
| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 |
|
||||
| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 |
|
||||
| test.cpp:92:8:92:14 | source1 | test.cpp:89:28:89:34 | source1 |
|
||||
| test.cpp:110:10:110:12 | (reference dereference) | test.cpp:109:9:109:14 | call to source |
|
||||
| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source |
|
||||
| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source |
|
||||
| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source |
|
||||
| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source |
|
||||
| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source |
|
||||
| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source |
|
||||
| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source |
|
||||
| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source |
|
||||
| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 |
|
||||
| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 |
|
||||
| true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source |
|
||||
| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source |
|
||||
| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source |
|
||||
| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source |
|
||||
| true_upon_entry.cpp:49:8:49:8 | x | true_upon_entry.cpp:43:11:43:16 | call to source |
|
||||
| true_upon_entry.cpp:57:8:57:8 | x | true_upon_entry.cpp:54:11:54:16 | call to source |
|
||||
| true_upon_entry.cpp:66:8:66:8 | x | true_upon_entry.cpp:62:11:62:16 | call to source |
|
||||
| true_upon_entry.cpp:78:8:78:8 | x | true_upon_entry.cpp:70:11:70:16 | call to source |
|
||||
| true_upon_entry.cpp:86:8:86:8 | x | true_upon_entry.cpp:83:11:83:16 | call to source |
|
||||
| true_upon_entry.cpp:105:8:105:8 | x | true_upon_entry.cpp:98:11:98:16 | call to source |
|
||||
|
||||
@@ -78,15 +78,15 @@ edges
|
||||
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 |
|
||||
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] |
|
||||
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] |
|
||||
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | `this` parameter in func [s1] |
|
||||
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | `this` parameter in func [s3] |
|
||||
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] |
|
||||
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | this [s3] |
|
||||
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] |
|
||||
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] |
|
||||
| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] |
|
||||
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] |
|
||||
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | C.cpp:29:10:29:11 | this [s1] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | C.cpp:31:10:31:11 | this [s3] |
|
||||
| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [s1] |
|
||||
| C.cpp:27:8:27:11 | this [s3] | C.cpp:31:10:31:11 | this [s3] |
|
||||
| C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 |
|
||||
| C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 |
|
||||
| D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] |
|
||||
@@ -117,8 +117,8 @@ edges
|
||||
| D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:58:5:58:27 | ... = ... | D.cpp:58:15:58:17 | box [post update] [elem] |
|
||||
| D.cpp:58:15:58:17 | box [post update] [elem] | D.cpp:58:5:58:12 | boxfield [post update] [box, elem] |
|
||||
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] |
|
||||
| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] |
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | boxfield [box, elem] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem |
|
||||
@@ -337,8 +337,8 @@ nodes
|
||||
| C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] |
|
||||
| C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... |
|
||||
| C.cpp:24:16:24:25 | new | semmle.label | new |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s1] | semmle.label | `this` parameter in func [s1] |
|
||||
| C.cpp:27:8:27:11 | `this` parameter in func [s3] | semmle.label | `this` parameter in func [s3] |
|
||||
| C.cpp:27:8:27:11 | this [s1] | semmle.label | this [s1] |
|
||||
| C.cpp:27:8:27:11 | this [s3] | semmle.label | this [s3] |
|
||||
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
|
||||
| C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] |
|
||||
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
|
||||
@@ -373,7 +373,7 @@ nodes
|
||||
| D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... |
|
||||
| D.cpp:58:15:58:17 | box [post update] [elem] | semmle.label | box [post update] [elem] |
|
||||
| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | semmle.label | `this` parameter in f5b [boxfield, box, ... (3)] |
|
||||
| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:10:64:17 | boxfield [box, elem] | semmle.label | boxfield [box, elem] |
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] |
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
| taint.cpp:37:12:37:20 | call to increment | taint.cpp:43:7:43:13 | global9 | |
|
||||
| taint.cpp:38:13:38:16 | call to zero | taint.cpp:38:2:38:26 | ... = ... | |
|
||||
| taint.cpp:38:13:38:16 | call to zero | taint.cpp:44:7:44:14 | global10 | |
|
||||
| taint.cpp:71:2:71:8 | `this` parameter in MyClass | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | |
|
||||
| taint.cpp:71:2:71:8 | this | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | |
|
||||
| taint.cpp:71:14:71:17 | 0 | taint.cpp:71:14:71:17 | constructor init of field a | TAINT |
|
||||
| taint.cpp:71:14:71:17 | constructor init of field a [post-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | |
|
||||
| taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | |
|
||||
@@ -56,7 +56,7 @@
|
||||
| taint.cpp:72:3:72:3 | this [post update] | taint.cpp:73:3:73:3 | this | |
|
||||
| taint.cpp:72:7:72:12 | call to source | taint.cpp:72:3:72:14 | ... = ... | |
|
||||
| taint.cpp:73:7:73:7 | 0 | taint.cpp:73:3:73:7 | ... = ... | |
|
||||
| taint.cpp:76:7:76:14 | `this` parameter in myMethod | taint.cpp:77:3:77:3 | this | |
|
||||
| taint.cpp:76:7:76:14 | this | taint.cpp:77:3:77:3 | this | |
|
||||
| taint.cpp:77:7:77:12 | call to source | taint.cpp:77:3:77:14 | ... = ... | |
|
||||
| taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:86:2:86:4 | mc1 | |
|
||||
| taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:88:7:88:9 | mc1 | |
|
||||
@@ -178,51 +178,51 @@
|
||||
| taint.cpp:213:15:213:15 | ref arg y | taint.cpp:216:7:216:7 | y | |
|
||||
| taint.cpp:213:15:213:15 | y | taint.cpp:213:12:213:12 | ref arg x | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:228:12:228:12 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:235:11:239:2 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:243:11:246:2 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:235:10:239:2 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:243:10:246:2 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:253:4:253:4 | t | |
|
||||
| taint.cpp:223:10:223:15 | call to source | taint.cpp:260:4:260:4 | t | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:228:15:228:15 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:235:11:239:2 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:243:11:246:2 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:235:10:239:2 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:243:10:246:2 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:253:7:253:7 | u | |
|
||||
| taint.cpp:224:9:224:10 | 0 | taint.cpp:260:7:260:7 | u | |
|
||||
| taint.cpp:225:9:225:10 | 0 | taint.cpp:235:11:239:2 | v | |
|
||||
| taint.cpp:225:9:225:10 | 0 | taint.cpp:235:10:239:2 | v | |
|
||||
| taint.cpp:225:9:225:10 | 0 | taint.cpp:241:7:241:7 | v | |
|
||||
| taint.cpp:226:9:226:10 | 0 | taint.cpp:260:10:260:10 | w | |
|
||||
| taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | |
|
||||
| taint.cpp:228:10:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
|
||||
| taint.cpp:228:10:232:2 | {...} | taint.cpp:228:10:232:2 | [...](...){...} | |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | |
|
||||
| taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | |
|
||||
| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | |
|
||||
| taint.cpp:228:11:228:11 | this | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:228:17:228:17 | this | taint.cpp:229:3:229:6 | this | |
|
||||
| taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | |
|
||||
| taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | |
|
||||
| taint.cpp:235:10:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
|
||||
| taint.cpp:235:10:239:2 | {...} | taint.cpp:235:10:239:2 | [...](...){...} | |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT |
|
||||
| taint.cpp:235:11:235:11 | `this` parameter in (constructor) | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [post-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [post-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | |
|
||||
| taint.cpp:235:11:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | |
|
||||
| taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | |
|
||||
| taint.cpp:235:15:235:15 | `this` parameter in operator() | taint.cpp:236:3:236:6 | this | |
|
||||
| taint.cpp:235:11:235:11 | this | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:235:15:235:15 | this | taint.cpp:236:3:236:6 | this | |
|
||||
| taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | |
|
||||
| taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | |
|
||||
| taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | |
|
||||
| taint.cpp:243:10:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
|
||||
| taint.cpp:243:10:246:2 | {...} | taint.cpp:243:10:246:2 | [...](...){...} | |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT |
|
||||
| taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT |
|
||||
| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | |
|
||||
| taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | |
|
||||
| taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | |
|
||||
| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | |
|
||||
| taint.cpp:243:11:243:11 | this | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | |
|
||||
| taint.cpp:243:15:243:15 | this | taint.cpp:244:3:244:6 | this | |
|
||||
| taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | |
|
||||
| taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | |
|
||||
| taint.cpp:249:18:249:18 | a | taint.cpp:250:8:250:8 | a | |
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
| taint.cpp:8:8:8:13 | Load: clean1 | taint.cpp:4:27:4:33 | InitializeParameter: source1 |
|
||||
| taint.cpp:16:8:16:14 | Load: source1 | taint.cpp:12:22:12:27 | Call: call to source |
|
||||
| taint.cpp:17:8:17:16 | Add: ++ ... | taint.cpp:12:22:12:27 | Call: call to source |
|
||||
| taint.cpp:109:7:109:13 | Load: access to array | taint.cpp:105:12:105:17 | Call: call to source |
|
||||
| taint.cpp:129:7:129:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source |
|
||||
| taint.cpp:130:7:130:9 | Load: * ... | taint.cpp:127:8:127:13 | Call: call to source |
|
||||
| taint.cpp:134:7:134:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source |
|
||||
| taint.cpp:151:7:151:12 | Call: call to select | taint.cpp:151:20:151:25 | Call: call to source |
|
||||
| taint.cpp:167:8:167:13 | Call: call to source | taint.cpp:167:8:167:13 | Call: call to source |
|
||||
| taint.cpp:168:8:168:14 | Load: tainted | taint.cpp:164:19:164:24 | Call: call to source |
|
||||
| taint.cpp:210:7:210:7 | Load: x | taint.cpp:207:6:207:11 | Call: call to source |
|
||||
| taint.cpp:280:7:280:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
|
||||
| taint.cpp:289:7:289:7 | Load: t | taint.cpp:275:6:275:11 | Call: call to source |
|
||||
| taint.cpp:290:7:290:7 | Load: x | taint.cpp:275:6:275:11 | Call: call to source |
|
||||
| taint.cpp:291:7:291:7 | Load: y | taint.cpp:275:6:275:11 | Call: call to source |
|
||||
| taint.cpp:337:7:337:7 | Load: t | taint.cpp:330:6:330:11 | Call: call to source |
|
||||
| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 |
|
||||
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
|
||||
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
|
||||
| taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source |
|
||||
| taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source |
|
||||
| taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source |
|
||||
| taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source |
|
||||
| taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source |
|
||||
| taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source |
|
||||
| taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source |
|
||||
| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source |
|
||||
| taint.cpp:280:7:280:7 | t | taint.cpp:275:6:275:11 | call to source |
|
||||
| taint.cpp:289:7:289:7 | t | taint.cpp:275:6:275:11 | call to source |
|
||||
| taint.cpp:290:7:290:7 | x | taint.cpp:275:6:275:11 | call to source |
|
||||
| taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source |
|
||||
| taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source |
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:38:20:38:25 | ... += ... |
|
||||
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:40:15:40:15 | i |
|
||||
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:42:18:42:22 | & ... |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:57:18:57:45 | ... + ... |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:58:18:58:18 | a |
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:37:18:37:26 | & ... | addressOf.cpp:38:20:38:20 | i |
|
||||
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:38:18:38:30 | ... + ... | addressOf.cpp:40:15:40:15 | i |
|
||||
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:40:15:40:15 | i | addressOf.cpp:42:19:42:22 | iref |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:48:3:48:4 | f1 |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} | addressOf.cpp:50:3:50:4 | f2 |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} | addressOf.cpp:48:3:48:4 | f1 |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} | addressOf.cpp:50:3:50:4 | f2 |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} | addressOf.cpp:57:19:57:19 | a |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:57:18:57:45 | ... + ... | addressOf.cpp:58:18:58:18 | a |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:20:14:20:15 | ip | indirect_use.cpp:21:17:21:17 | p |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:47:13:47:31 | [...](...){...} |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} | addressOf.cpp:49:13:49:39 | [...](...){...} |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:12:47:31 | [...](...){...} | addressOf.cpp:47:12:47:31 | [...](...){...} |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:12:49:39 | [...](...){...} | addressOf.cpp:49:12:49:39 | [...](...){...} |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} | addressOf.cpp:56:13:56:28 | {...} |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:20:14:20:15 | ip | indirect_use.cpp:20:14:20:15 | ip |
|
||||
| indirect_use.cpp:25:10:25:10 | p | indirect_use.cpp:25:14:25:19 | ... + ... | indirect_use.cpp:25:14:25:19 | ... + ... |
|
||||
|
||||
@@ -3732,7 +3732,7 @@ ir.cpp:
|
||||
# 572| Type = [ArrayType] char[32]
|
||||
# 572| init: [Initializer] initializer for a_pad
|
||||
# 572| expr:
|
||||
# 572| Type = [ArrayType] const char[1]
|
||||
# 572| Type = [ArrayType] const char[32]
|
||||
# 572| Value = [StringLiteral] ""
|
||||
# 572| ValueCategory = lvalue
|
||||
# 573| 1: [DeclStmt] declaration
|
||||
@@ -6894,9 +6894,6 @@ ir.cpp:
|
||||
# 1029| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1029, col. 12 &&
|
||||
# 1029| initializations:
|
||||
# 1029| body: [Block] { ... }
|
||||
# 1029| 0: [ReturnStmt] return ...
|
||||
# 1029| [Constructor] void (lambda [] type at line 1029, col. 12)::(constructor)()
|
||||
# 1029| params:
|
||||
# 1029| [MemberFunction] void (lambda [] type at line 1029, col. 12)::_FUN()
|
||||
@@ -6996,24 +6993,18 @@ ir.cpp:
|
||||
# 1036| 0: [VariableDeclarationEntry] definition of lambda_val
|
||||
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1036| init: [Initializer] initializer for lambda_val
|
||||
# 1036| expr: [ConstructorCall] call to (constructor)
|
||||
# 1036| Type = [VoidType] void
|
||||
# 1036| expr: [LambdaExpression] [...](...){...}
|
||||
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| 0: [ReferenceToExpr] (reference to)
|
||||
# 1036| Type = [LValueReferenceType] lambda [] type at line 1036, col. 21 &
|
||||
# 1036| 0: [ClassAggregateLiteral] {...}
|
||||
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| expr: [LambdaExpression] [...](...){...}
|
||||
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1036| ValueCategory = xvalue
|
||||
# 1036| 0: [ClassAggregateLiteral] {...}
|
||||
# 1036| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1036| ValueCategory = prvalue
|
||||
#-----| .s: [ConstructorCall] call to String
|
||||
#-----| Type = [VoidType] void
|
||||
#-----| ValueCategory = prvalue
|
||||
#-----| .x: [VariableAccess] x
|
||||
#-----| Type = [IntType] int
|
||||
#-----| ValueCategory = prvalue(load)
|
||||
#-----| .s: [ConstructorCall] call to String
|
||||
#-----| Type = [VoidType] void
|
||||
#-----| ValueCategory = prvalue
|
||||
#-----| .x: [VariableAccess] x
|
||||
#-----| Type = [IntType] int
|
||||
#-----| ValueCategory = prvalue(load)
|
||||
# 1037| 5: [ExprStmt] ExprStmt
|
||||
# 1037| 0: [FunctionCall] call to operator()
|
||||
# 1037| Type = [PlainCharType] char
|
||||
@@ -7077,21 +7068,15 @@ ir.cpp:
|
||||
# 1040| 0: [VariableDeclarationEntry] definition of lambda_val_explicit
|
||||
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1040| init: [Initializer] initializer for lambda_val_explicit
|
||||
# 1040| expr: [ConstructorCall] call to (constructor)
|
||||
# 1040| Type = [VoidType] void
|
||||
# 1040| expr: [LambdaExpression] [...](...){...}
|
||||
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1040| ValueCategory = prvalue
|
||||
# 1040| 0: [ReferenceToExpr] (reference to)
|
||||
# 1040| Type = [LValueReferenceType] lambda [] type at line 1040, col. 30 &
|
||||
# 1040| 0: [ClassAggregateLiteral] {...}
|
||||
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1040| ValueCategory = prvalue
|
||||
# 1040| expr: [LambdaExpression] [...](...){...}
|
||||
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1040| ValueCategory = xvalue
|
||||
# 1040| 0: [ClassAggregateLiteral] {...}
|
||||
# 1040| Type = [Closure,LocalClass] decltype([...](...){...})
|
||||
# 1040| ValueCategory = prvalue
|
||||
#-----| .s: [ConstructorCall] call to String
|
||||
#-----| Type = [VoidType] void
|
||||
#-----| ValueCategory = prvalue
|
||||
#-----| .s: [ConstructorCall] call to String
|
||||
#-----| Type = [VoidType] void
|
||||
#-----| ValueCategory = prvalue
|
||||
# 1041| 9: [ExprStmt] ExprStmt
|
||||
# 1041| 0: [FunctionCall] call to operator()
|
||||
# 1041| Type = [PlainCharType] char
|
||||
@@ -7239,9 +7224,6 @@ ir.cpp:
|
||||
# 1032| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1032, col. 23 &&
|
||||
# 1032| initializations:
|
||||
# 1032| body: [Block] { ... }
|
||||
# 1032| 0: [ReturnStmt] return ...
|
||||
# 1032| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)()
|
||||
# 1032| params:
|
||||
# 1032| [MemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::_FUN(float)
|
||||
@@ -7277,21 +7259,6 @@ ir.cpp:
|
||||
# 1034| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1034, col. 21 &&
|
||||
# 1034| initializations:
|
||||
# 1034| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1034| Type = [LValueReferenceType] const String &
|
||||
# 1034| ValueCategory = prvalue
|
||||
# 1034| 0: [Literal] Unknown literal
|
||||
# 1034| Type = [LValueReferenceType] const String &
|
||||
# 1034| ValueCategory = prvalue
|
||||
# 1034| 1: [ConstructorFieldInit] constructor init of field x
|
||||
# 1034| Type = [LValueReferenceType] int &
|
||||
# 1034| ValueCategory = prvalue
|
||||
# 1034| 0: [Literal] Unknown literal
|
||||
# 1034| Type = [LValueReferenceType] int &
|
||||
# 1034| ValueCategory = prvalue
|
||||
# 1034| body: [Block] { ... }
|
||||
# 1034| 0: [ReturnStmt] return ...
|
||||
# 1034| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1034, col. 21)::(constructor)()
|
||||
# 1034| params:
|
||||
# 1034| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1034, col. 21)::operator()(float) const
|
||||
@@ -7336,21 +7303,6 @@ ir.cpp:
|
||||
# 1036| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1036, col. 21 &&
|
||||
# 1036| initializations:
|
||||
# 1036| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1036| Type = [SpecifiedType] const String
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| 0: [ConstructorCall] call to String
|
||||
# 1036| Type = [VoidType] void
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| 1: [ConstructorFieldInit] constructor init of field x
|
||||
# 1036| Type = [IntType] int
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| 0: [Literal] Unknown literal
|
||||
# 1036| Type = [IntType] int
|
||||
# 1036| ValueCategory = prvalue
|
||||
# 1036| body: [Block] { ... }
|
||||
# 1036| 0: [ReturnStmt] return ...
|
||||
# 1036| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::(constructor)()
|
||||
# 1036| params:
|
||||
# 1036| [Destructor] void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::~<unnamed>()
|
||||
@@ -7403,15 +7355,6 @@ ir.cpp:
|
||||
# 1038| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1038, col. 30 &&
|
||||
# 1038| initializations:
|
||||
# 1038| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1038| Type = [LValueReferenceType] const String &
|
||||
# 1038| ValueCategory = prvalue
|
||||
# 1038| 0: [Literal] Unknown literal
|
||||
# 1038| Type = [LValueReferenceType] const String &
|
||||
# 1038| ValueCategory = prvalue
|
||||
# 1038| body: [Block] { ... }
|
||||
# 1038| 0: [ReturnStmt] return ...
|
||||
# 1038| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1038, col. 30)::(constructor)()
|
||||
# 1038| params:
|
||||
# 1038| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1038, col. 30)::operator()(float) const
|
||||
@@ -7451,15 +7394,6 @@ ir.cpp:
|
||||
# 1040| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1040, col. 30 &&
|
||||
# 1040| initializations:
|
||||
# 1040| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1040| Type = [SpecifiedType] const String
|
||||
# 1040| ValueCategory = prvalue
|
||||
# 1040| 0: [ConstructorCall] call to String
|
||||
# 1040| Type = [VoidType] void
|
||||
# 1040| ValueCategory = prvalue
|
||||
# 1040| body: [Block] { ... }
|
||||
# 1040| 0: [ReturnStmt] return ...
|
||||
# 1040| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)()
|
||||
# 1040| params:
|
||||
# 1040| [Destructor] void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~<unnamed>()
|
||||
@@ -7510,21 +7444,6 @@ ir.cpp:
|
||||
# 1042| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1042, col. 32 &&
|
||||
# 1042| initializations:
|
||||
# 1042| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1042| Type = [LValueReferenceType] const String &
|
||||
# 1042| ValueCategory = prvalue
|
||||
# 1042| 0: [Literal] Unknown literal
|
||||
# 1042| Type = [LValueReferenceType] const String &
|
||||
# 1042| ValueCategory = prvalue
|
||||
# 1042| 1: [ConstructorFieldInit] constructor init of field x
|
||||
# 1042| Type = [IntType] int
|
||||
# 1042| ValueCategory = prvalue
|
||||
# 1042| 0: [Literal] Unknown literal
|
||||
# 1042| Type = [IntType] int
|
||||
# 1042| ValueCategory = prvalue
|
||||
# 1042| body: [Block] { ... }
|
||||
# 1042| 0: [ReturnStmt] return ...
|
||||
# 1042| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1042, col. 32)::(constructor)()
|
||||
# 1042| params:
|
||||
# 1042| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1042, col. 32)::operator()(float) const
|
||||
@@ -7566,33 +7485,6 @@ ir.cpp:
|
||||
# 1045| params:
|
||||
#-----| 0: [Parameter] p#0
|
||||
#-----| Type = [RValueReferenceType] lambda [] type at line 1045, col. 23 &&
|
||||
# 1045| initializations:
|
||||
# 1045| 0: [ConstructorFieldInit] constructor init of field s
|
||||
# 1045| Type = [LValueReferenceType] const String &
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 0: [Literal] Unknown literal
|
||||
# 1045| Type = [LValueReferenceType] const String &
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 1: [ConstructorFieldInit] constructor init of field x
|
||||
# 1045| Type = [IntType] int
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 0: [Literal] Unknown literal
|
||||
# 1045| Type = [IntType] int
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 2: [ConstructorFieldInit] constructor init of field i
|
||||
# 1045| Type = [IntType] int
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 0: [Literal] Unknown literal
|
||||
# 1045| Type = [IntType] int
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 3: [ConstructorFieldInit] constructor init of field j
|
||||
# 1045| Type = [LValueReferenceType] int &
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| 0: [Literal] Unknown literal
|
||||
# 1045| Type = [LValueReferenceType] int &
|
||||
# 1045| ValueCategory = prvalue
|
||||
# 1045| body: [Block] { ... }
|
||||
# 1045| 0: [ReturnStmt] return ...
|
||||
# 1045| [Constructor] void (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::(constructor)()
|
||||
# 1045| params:
|
||||
# 1045| [ConstMemberFunction] char (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::operator()(float) const
|
||||
|
||||
@@ -2700,65 +2700,60 @@ ir.cpp:
|
||||
# 571| mu0_1(unknown) = AliasedDefinition :
|
||||
# 571| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 572| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
|
||||
# 572| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
|
||||
# 572| r0_5(glval<char[1]>) = StringConstant[""] :
|
||||
# 572| r0_6(char[1]) = Load : &:r0_5, ~mu0_2
|
||||
# 572| mu0_7(char[1]) = Store : &:r0_3, r0_6
|
||||
# 572| r0_8(unknown[31]) = Constant[0] :
|
||||
# 572| r0_9(int) = Constant[1] :
|
||||
# 572| r0_10(glval<char>) = PointerAdd[1] : r0_3, r0_9
|
||||
# 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8
|
||||
# 573| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 573| r0_13(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 573| r0_14(char[4]) = Load : &:r0_13, ~mu0_2
|
||||
# 573| mu0_15(char[4]) = Store : &:r0_12, r0_14
|
||||
# 574| r0_16(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 574| r0_17(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 574| r0_18(char[5]) = Load : &:r0_17, ~mu0_2
|
||||
# 574| mu0_19(char[5]) = Store : &:r0_16, r0_18
|
||||
# 575| r0_20(glval<char[2]>) = VariableAddress[b] :
|
||||
# 575| mu0_21(char[2]) = Uninitialized[b] : &:r0_20
|
||||
# 576| r0_22(glval<char[2]>) = VariableAddress[c] :
|
||||
# 576| mu0_23(char[2]) = Uninitialized[c] : &:r0_22
|
||||
# 576| r0_24(int) = Constant[0] :
|
||||
# 576| r0_25(glval<char>) = PointerAdd[1] : r0_22, r0_24
|
||||
# 576| r0_26(unknown[2]) = Constant[0] :
|
||||
# 576| mu0_27(unknown[2]) = Store : &:r0_25, r0_26
|
||||
# 577| r0_28(glval<char[2]>) = VariableAddress[d] :
|
||||
# 577| mu0_29(char[2]) = Uninitialized[d] : &:r0_28
|
||||
# 577| r0_30(int) = Constant[0] :
|
||||
# 577| r0_31(glval<char>) = PointerAdd[1] : r0_28, r0_30
|
||||
# 577| r0_32(char) = Constant[0] :
|
||||
# 577| mu0_33(char) = Store : &:r0_31, r0_32
|
||||
# 577| r0_34(int) = Constant[1] :
|
||||
# 577| r0_35(glval<char>) = PointerAdd[1] : r0_28, r0_34
|
||||
# 577| r0_36(char) = Constant[0] :
|
||||
# 577| mu0_37(char) = Store : &:r0_35, r0_36
|
||||
# 578| r0_38(glval<char[2]>) = VariableAddress[e] :
|
||||
# 578| mu0_39(char[2]) = Uninitialized[e] : &:r0_38
|
||||
# 578| r0_40(int) = Constant[0] :
|
||||
# 578| r0_41(glval<char>) = PointerAdd[1] : r0_38, r0_40
|
||||
# 578| r0_42(char) = Constant[0] :
|
||||
# 578| mu0_43(char) = Store : &:r0_41, r0_42
|
||||
# 578| r0_44(int) = Constant[1] :
|
||||
# 578| r0_45(glval<char>) = PointerAdd[1] : r0_38, r0_44
|
||||
# 578| r0_46(char) = Constant[1] :
|
||||
# 578| mu0_47(char) = Store : &:r0_45, r0_46
|
||||
# 579| r0_48(glval<char[3]>) = VariableAddress[f] :
|
||||
# 579| mu0_49(char[3]) = Uninitialized[f] : &:r0_48
|
||||
# 579| r0_50(int) = Constant[0] :
|
||||
# 579| r0_51(glval<char>) = PointerAdd[1] : r0_48, r0_50
|
||||
# 579| r0_52(char) = Constant[0] :
|
||||
# 579| mu0_53(char) = Store : &:r0_51, r0_52
|
||||
# 579| r0_54(int) = Constant[1] :
|
||||
# 579| r0_55(glval<char>) = PointerAdd[1] : r0_48, r0_54
|
||||
# 579| r0_56(unknown[2]) = Constant[0] :
|
||||
# 579| mu0_57(unknown[2]) = Store : &:r0_55, r0_56
|
||||
# 580| v0_58(void) = NoOp :
|
||||
# 571| v0_59(void) = ReturnVoid :
|
||||
# 571| v0_60(void) = UnmodeledUse : mu*
|
||||
# 571| v0_61(void) = AliasedUse : ~mu0_2
|
||||
# 571| v0_62(void) = ExitFunction :
|
||||
# 572| r0_4(glval<char[32]>) = StringConstant[""] :
|
||||
# 572| r0_5(char[32]) = Load : &:r0_4, ~mu0_2
|
||||
# 572| mu0_6(char[32]) = Store : &:r0_3, r0_5
|
||||
# 573| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 573| r0_8(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 573| r0_9(char[4]) = Load : &:r0_8, ~mu0_2
|
||||
# 573| mu0_10(char[4]) = Store : &:r0_7, r0_9
|
||||
# 574| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 574| r0_12(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 574| r0_13(char[5]) = Load : &:r0_12, ~mu0_2
|
||||
# 574| mu0_14(char[5]) = Store : &:r0_11, r0_13
|
||||
# 575| r0_15(glval<char[2]>) = VariableAddress[b] :
|
||||
# 575| mu0_16(char[2]) = Uninitialized[b] : &:r0_15
|
||||
# 576| r0_17(glval<char[2]>) = VariableAddress[c] :
|
||||
# 576| mu0_18(char[2]) = Uninitialized[c] : &:r0_17
|
||||
# 576| r0_19(int) = Constant[0] :
|
||||
# 576| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
|
||||
# 576| r0_21(unknown[2]) = Constant[0] :
|
||||
# 576| mu0_22(unknown[2]) = Store : &:r0_20, r0_21
|
||||
# 577| r0_23(glval<char[2]>) = VariableAddress[d] :
|
||||
# 577| mu0_24(char[2]) = Uninitialized[d] : &:r0_23
|
||||
# 577| r0_25(int) = Constant[0] :
|
||||
# 577| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
|
||||
# 577| r0_27(char) = Constant[0] :
|
||||
# 577| mu0_28(char) = Store : &:r0_26, r0_27
|
||||
# 577| r0_29(int) = Constant[1] :
|
||||
# 577| r0_30(glval<char>) = PointerAdd[1] : r0_23, r0_29
|
||||
# 577| r0_31(char) = Constant[0] :
|
||||
# 577| mu0_32(char) = Store : &:r0_30, r0_31
|
||||
# 578| r0_33(glval<char[2]>) = VariableAddress[e] :
|
||||
# 578| mu0_34(char[2]) = Uninitialized[e] : &:r0_33
|
||||
# 578| r0_35(int) = Constant[0] :
|
||||
# 578| r0_36(glval<char>) = PointerAdd[1] : r0_33, r0_35
|
||||
# 578| r0_37(char) = Constant[0] :
|
||||
# 578| mu0_38(char) = Store : &:r0_36, r0_37
|
||||
# 578| r0_39(int) = Constant[1] :
|
||||
# 578| r0_40(glval<char>) = PointerAdd[1] : r0_33, r0_39
|
||||
# 578| r0_41(char) = Constant[1] :
|
||||
# 578| mu0_42(char) = Store : &:r0_40, r0_41
|
||||
# 579| r0_43(glval<char[3]>) = VariableAddress[f] :
|
||||
# 579| mu0_44(char[3]) = Uninitialized[f] : &:r0_43
|
||||
# 579| r0_45(int) = Constant[0] :
|
||||
# 579| r0_46(glval<char>) = PointerAdd[1] : r0_43, r0_45
|
||||
# 579| r0_47(char) = Constant[0] :
|
||||
# 579| mu0_48(char) = Store : &:r0_46, r0_47
|
||||
# 579| r0_49(int) = Constant[1] :
|
||||
# 579| r0_50(glval<char>) = PointerAdd[1] : r0_43, r0_49
|
||||
# 579| r0_51(unknown[2]) = Constant[0] :
|
||||
# 579| mu0_52(unknown[2]) = Store : &:r0_50, r0_51
|
||||
# 580| v0_53(void) = NoOp :
|
||||
# 571| v0_54(void) = ReturnVoid :
|
||||
# 571| v0_55(void) = UnmodeledUse : mu*
|
||||
# 571| v0_56(void) = AliasedUse : ~mu0_2
|
||||
# 571| v0_57(void) = ExitFunction :
|
||||
|
||||
# 584| void VarArgs()
|
||||
# 584| Block 0
|
||||
@@ -4898,20 +4893,6 @@ ir.cpp:
|
||||
# 1025| v0_8(void) = AliasedUse : ~mu0_2
|
||||
# 1025| v0_9(void) = ExitFunction :
|
||||
|
||||
# 1029| void (lambda [] type at line 1029, col. 12)::(constructor)((lambda [] type at line 1029, col. 12)&&)
|
||||
# 1029| Block 0
|
||||
# 1029| v0_0(void) = EnterFunction :
|
||||
# 1029| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1029| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1029| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
|
||||
#-----| r0_4(glval<lambda [] type at line 1029, col. 12 &&>) = VariableAddress[p#0] :
|
||||
#-----| mu0_5(lambda [] type at line 1029, col. 12 &&) = InitializeParameter[p#0] : &:r0_4
|
||||
# 1029| v0_6(void) = NoOp :
|
||||
# 1029| v0_7(void) = ReturnVoid :
|
||||
# 1029| v0_8(void) = UnmodeledUse : mu*
|
||||
# 1029| v0_9(void) = AliasedUse : ~mu0_2
|
||||
# 1029| v0_10(void) = ExitFunction :
|
||||
|
||||
# 1029| void (lambda [] type at line 1029, col. 12)::operator()() const
|
||||
# 1029| Block 0
|
||||
# 1029| v0_0(void) = EnterFunction :
|
||||
@@ -4941,196 +4922,168 @@ ir.cpp:
|
||||
|
||||
# 1031| void Lambda(int, String const&)
|
||||
# 1031| Block 0
|
||||
# 1031| v0_0(void) = EnterFunction :
|
||||
# 1031| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1031| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1031| r0_3(glval<int>) = VariableAddress[x] :
|
||||
# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3
|
||||
# 1031| r0_5(glval<String &>) = VariableAddress[s] :
|
||||
# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5
|
||||
# 1032| r0_7(glval<decltype([...](...){...})>) = VariableAddress[lambda_empty] :
|
||||
# 1032| r0_8(glval<decltype([...](...){...})>) = VariableAddress[#temp1032:23] :
|
||||
# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8
|
||||
# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2
|
||||
# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10
|
||||
# 1033| r0_12(char) = Constant[65] :
|
||||
# 1034| r0_13(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
|
||||
# 1034| r0_14(glval<decltype([...](...){...})>) = VariableAddress[#temp1034:21] :
|
||||
# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14
|
||||
# 1034| r0_16(glval<String &>) = FieldAddress[s] : r0_14
|
||||
#-----| r0_17(glval<String &>) = VariableAddress[s] :
|
||||
#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2
|
||||
# 1034| r0_19(glval<String>) = CopyValue : r0_18
|
||||
# 1034| r0_20(String &) = CopyValue : r0_19
|
||||
# 1034| mu0_21(String &) = Store : &:r0_16, r0_20
|
||||
# 1034| r0_22(glval<int &>) = FieldAddress[x] : r0_14
|
||||
#-----| r0_23(glval<int>) = VariableAddress[x] :
|
||||
#-----| r0_24(int &) = CopyValue : r0_23
|
||||
#-----| mu0_25(int &) = Store : &:r0_22, r0_24
|
||||
# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2
|
||||
# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26
|
||||
# 1035| r0_28(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
|
||||
# 1035| r0_29(glval<decltype([...](...){...})>) = Convert : r0_28
|
||||
# 1035| r0_30(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1035| r0_31(float) = Constant[1.0] :
|
||||
# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31
|
||||
# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1035| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
|
||||
# 1035| mu0_35(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
|
||||
# 1036| r0_36(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
|
||||
# 1036| mu0_37(decltype([...](...){...})) = Uninitialized[lambda_val] : &:r0_36
|
||||
# 1036| r0_38(glval<unknown>) = FunctionAddress[(constructor)] :
|
||||
# 1036| r0_39(glval<decltype([...](...){...})>) = VariableAddress[#temp1036:21] :
|
||||
# 1036| mu0_40(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_39
|
||||
# 1036| r0_41(glval<String>) = FieldAddress[s] : r0_39
|
||||
#-----| r0_42(glval<unknown>) = FunctionAddress[String] :
|
||||
#-----| v0_43(void) = Call : func:r0_42, this:r0_41
|
||||
#-----| mu0_44(unknown) = ^CallSideEffect : ~mu0_2
|
||||
#-----| mu0_45(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_41
|
||||
# 1036| r0_46(glval<int>) = FieldAddress[x] : r0_39
|
||||
#-----| r0_47(glval<int>) = VariableAddress[x] :
|
||||
#-----| r0_48(int) = Load : &:r0_47, ~mu0_2
|
||||
#-----| mu0_49(int) = Store : &:r0_46, r0_48
|
||||
# 1036| r0_50(decltype([...](...){...})) = Load : &:r0_39, ~mu0_2
|
||||
# 1036| r0_51(lambda [] type at line 1036, col. 21 &) = CopyValue : r0_50
|
||||
# 1036| v0_52(void) = Call : func:r0_38, this:r0_36, 0:r0_51
|
||||
# 1036| mu0_53(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1036| mu0_54(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_36
|
||||
# 1036| v0_55(void) = ^BufferReadSideEffect[0] : &:r0_51, ~mu0_2
|
||||
# 1036| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_51
|
||||
# 1037| r0_57(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
|
||||
# 1037| r0_58(glval<decltype([...](...){...})>) = Convert : r0_57
|
||||
# 1037| r0_59(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1037| r0_60(float) = Constant[2.0] :
|
||||
# 1037| r0_61(char) = Call : func:r0_59, this:r0_58, 0:r0_60
|
||||
# 1037| mu0_62(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1037| v0_63(void) = ^BufferReadSideEffect[-1] : &:r0_58, ~mu0_2
|
||||
# 1037| mu0_64(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_58
|
||||
# 1038| r0_65(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
|
||||
# 1038| r0_66(glval<decltype([...](...){...})>) = VariableAddress[#temp1038:30] :
|
||||
# 1038| mu0_67(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_66
|
||||
# 1038| r0_68(glval<String &>) = FieldAddress[s] : r0_66
|
||||
# 1038| r0_69(glval<String &>) = VariableAddress[s] :
|
||||
# 1038| r0_70(String &) = Load : &:r0_69, ~mu0_2
|
||||
# 1038| r0_71(glval<String>) = CopyValue : r0_70
|
||||
# 1038| r0_72(String &) = CopyValue : r0_71
|
||||
# 1038| mu0_73(String &) = Store : &:r0_68, r0_72
|
||||
# 1038| r0_74(decltype([...](...){...})) = Load : &:r0_66, ~mu0_2
|
||||
# 1038| mu0_75(decltype([...](...){...})) = Store : &:r0_65, r0_74
|
||||
# 1039| r0_76(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
|
||||
# 1039| r0_77(glval<decltype([...](...){...})>) = Convert : r0_76
|
||||
# 1039| r0_78(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1039| r0_79(float) = Constant[3.0] :
|
||||
# 1039| r0_80(char) = Call : func:r0_78, this:r0_77, 0:r0_79
|
||||
# 1039| mu0_81(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1039| v0_82(void) = ^BufferReadSideEffect[-1] : &:r0_77, ~mu0_2
|
||||
# 1039| mu0_83(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_77
|
||||
# 1040| r0_84(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
|
||||
# 1040| mu0_85(decltype([...](...){...})) = Uninitialized[lambda_val_explicit] : &:r0_84
|
||||
# 1040| r0_86(glval<unknown>) = FunctionAddress[(constructor)] :
|
||||
# 1040| r0_87(glval<decltype([...](...){...})>) = VariableAddress[#temp1040:30] :
|
||||
# 1040| mu0_88(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_87
|
||||
# 1040| r0_89(glval<String>) = FieldAddress[s] : r0_87
|
||||
#-----| r0_90(glval<unknown>) = FunctionAddress[String] :
|
||||
#-----| v0_91(void) = Call : func:r0_90, this:r0_89
|
||||
#-----| mu0_92(unknown) = ^CallSideEffect : ~mu0_2
|
||||
#-----| mu0_93(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_89
|
||||
# 1040| r0_94(decltype([...](...){...})) = Load : &:r0_87, ~mu0_2
|
||||
# 1040| r0_95(lambda [] type at line 1040, col. 30 &) = CopyValue : r0_94
|
||||
# 1040| v0_96(void) = Call : func:r0_86, this:r0_84, 0:r0_95
|
||||
# 1040| mu0_97(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1040| mu0_98(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_84
|
||||
# 1040| v0_99(void) = ^BufferReadSideEffect[0] : &:r0_95, ~mu0_2
|
||||
# 1040| mu0_100(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_95
|
||||
# 1041| r0_101(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
|
||||
# 1041| r0_102(glval<decltype([...](...){...})>) = Convert : r0_101
|
||||
# 1041| r0_103(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1041| r0_104(float) = Constant[4.0] :
|
||||
# 1041| r0_105(char) = Call : func:r0_103, this:r0_102, 0:r0_104
|
||||
# 1041| mu0_106(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1041| v0_107(void) = ^BufferReadSideEffect[-1] : &:r0_102, ~mu0_2
|
||||
# 1041| mu0_108(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_102
|
||||
# 1042| r0_109(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
|
||||
# 1042| r0_110(glval<decltype([...](...){...})>) = VariableAddress[#temp1042:32] :
|
||||
# 1042| mu0_111(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_110
|
||||
# 1042| r0_112(glval<String &>) = FieldAddress[s] : r0_110
|
||||
# 1042| r0_113(glval<String &>) = VariableAddress[s] :
|
||||
# 1042| r0_114(String &) = Load : &:r0_113, ~mu0_2
|
||||
# 1042| r0_115(glval<String>) = CopyValue : r0_114
|
||||
# 1042| r0_116(String &) = CopyValue : r0_115
|
||||
# 1042| mu0_117(String &) = Store : &:r0_112, r0_116
|
||||
# 1042| r0_118(glval<int>) = FieldAddress[x] : r0_110
|
||||
# 1042| r0_119(glval<int>) = VariableAddress[x] :
|
||||
# 1042| r0_120(int) = Load : &:r0_119, ~mu0_2
|
||||
# 1042| mu0_121(int) = Store : &:r0_118, r0_120
|
||||
# 1042| r0_122(decltype([...](...){...})) = Load : &:r0_110, ~mu0_2
|
||||
# 1042| mu0_123(decltype([...](...){...})) = Store : &:r0_109, r0_122
|
||||
# 1043| r0_124(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
|
||||
# 1043| r0_125(glval<decltype([...](...){...})>) = Convert : r0_124
|
||||
# 1043| r0_126(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1043| r0_127(float) = Constant[5.0] :
|
||||
# 1043| r0_128(char) = Call : func:r0_126, this:r0_125, 0:r0_127
|
||||
# 1043| mu0_129(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1043| v0_130(void) = ^BufferReadSideEffect[-1] : &:r0_125, ~mu0_2
|
||||
# 1043| mu0_131(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_125
|
||||
# 1044| r0_132(glval<int>) = VariableAddress[r] :
|
||||
# 1044| r0_133(glval<int>) = VariableAddress[x] :
|
||||
# 1044| r0_134(int) = Load : &:r0_133, ~mu0_2
|
||||
# 1044| r0_135(int) = Constant[1] :
|
||||
# 1044| r0_136(int) = Sub : r0_134, r0_135
|
||||
# 1044| mu0_137(int) = Store : &:r0_132, r0_136
|
||||
# 1045| r0_138(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
|
||||
# 1045| r0_139(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:23] :
|
||||
# 1045| mu0_140(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_139
|
||||
# 1045| r0_141(glval<String &>) = FieldAddress[s] : r0_139
|
||||
# 1045| r0_142(glval<String &>) = VariableAddress[s] :
|
||||
# 1045| r0_143(String &) = Load : &:r0_142, ~mu0_2
|
||||
# 1045| r0_144(glval<String>) = CopyValue : r0_143
|
||||
# 1045| r0_145(String &) = CopyValue : r0_144
|
||||
# 1045| mu0_146(String &) = Store : &:r0_141, r0_145
|
||||
# 1045| r0_147(glval<int>) = FieldAddress[x] : r0_139
|
||||
# 1045| r0_148(glval<int>) = VariableAddress[x] :
|
||||
# 1045| r0_149(int) = Load : &:r0_148, ~mu0_2
|
||||
# 1045| mu0_150(int) = Store : &:r0_147, r0_149
|
||||
# 1045| r0_151(glval<int>) = FieldAddress[i] : r0_139
|
||||
# 1045| r0_152(glval<int>) = VariableAddress[x] :
|
||||
# 1045| r0_153(int) = Load : &:r0_152, ~mu0_2
|
||||
# 1045| r0_154(int) = Constant[1] :
|
||||
# 1045| r0_155(int) = Add : r0_153, r0_154
|
||||
# 1045| mu0_156(int) = Store : &:r0_151, r0_155
|
||||
# 1045| r0_157(glval<int &>) = FieldAddress[j] : r0_139
|
||||
# 1045| r0_158(glval<int>) = VariableAddress[r] :
|
||||
# 1045| r0_159(int &) = CopyValue : r0_158
|
||||
# 1045| mu0_160(int &) = Store : &:r0_157, r0_159
|
||||
# 1045| r0_161(decltype([...](...){...})) = Load : &:r0_139, ~mu0_2
|
||||
# 1045| mu0_162(decltype([...](...){...})) = Store : &:r0_138, r0_161
|
||||
# 1046| r0_163(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
|
||||
# 1046| r0_164(glval<decltype([...](...){...})>) = Convert : r0_163
|
||||
# 1046| r0_165(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1046| r0_166(float) = Constant[6.0] :
|
||||
# 1046| r0_167(char) = Call : func:r0_165, this:r0_164, 0:r0_166
|
||||
# 1046| mu0_168(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1046| v0_169(void) = ^BufferReadSideEffect[-1] : &:r0_164, ~mu0_2
|
||||
# 1046| mu0_170(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_164
|
||||
# 1047| v0_171(void) = NoOp :
|
||||
# 1031| v0_172(void) = ReturnVoid :
|
||||
# 1031| v0_173(void) = UnmodeledUse : mu*
|
||||
# 1031| v0_174(void) = AliasedUse : ~mu0_2
|
||||
# 1031| v0_175(void) = ExitFunction :
|
||||
|
||||
# 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&)
|
||||
# 1032| Block 0
|
||||
# 1032| v0_0(void) = EnterFunction :
|
||||
# 1032| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1032| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1032| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
|
||||
#-----| r0_4(glval<lambda [] type at line 1032, col. 23 &&>) = VariableAddress[p#0] :
|
||||
#-----| mu0_5(lambda [] type at line 1032, col. 23 &&) = InitializeParameter[p#0] : &:r0_4
|
||||
# 1032| v0_6(void) = NoOp :
|
||||
# 1032| v0_7(void) = ReturnVoid :
|
||||
# 1032| v0_8(void) = UnmodeledUse : mu*
|
||||
# 1032| v0_9(void) = AliasedUse : ~mu0_2
|
||||
# 1032| v0_10(void) = ExitFunction :
|
||||
# 1031| v0_0(void) = EnterFunction :
|
||||
# 1031| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1031| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1031| r0_3(glval<int>) = VariableAddress[x] :
|
||||
# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3
|
||||
# 1031| r0_5(glval<String &>) = VariableAddress[s] :
|
||||
# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5
|
||||
# 1032| r0_7(glval<decltype([...](...){...})>) = VariableAddress[lambda_empty] :
|
||||
# 1032| r0_8(glval<decltype([...](...){...})>) = VariableAddress[#temp1032:23] :
|
||||
# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8
|
||||
# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2
|
||||
# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10
|
||||
# 1033| r0_12(char) = Constant[65] :
|
||||
# 1034| r0_13(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
|
||||
# 1034| r0_14(glval<decltype([...](...){...})>) = VariableAddress[#temp1034:20] :
|
||||
# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:20] : &:r0_14
|
||||
# 1034| r0_16(glval<String &>) = FieldAddress[s] : r0_14
|
||||
#-----| r0_17(glval<String &>) = VariableAddress[s] :
|
||||
#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2
|
||||
# 1034| r0_19(glval<String>) = CopyValue : r0_18
|
||||
# 1034| r0_20(String &) = CopyValue : r0_19
|
||||
# 1034| mu0_21(String &) = Store : &:r0_16, r0_20
|
||||
# 1034| r0_22(glval<int &>) = FieldAddress[x] : r0_14
|
||||
#-----| r0_23(glval<int>) = VariableAddress[x] :
|
||||
#-----| r0_24(int &) = CopyValue : r0_23
|
||||
#-----| mu0_25(int &) = Store : &:r0_22, r0_24
|
||||
# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2
|
||||
# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26
|
||||
# 1035| r0_28(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref] :
|
||||
# 1035| r0_29(glval<decltype([...](...){...})>) = Convert : r0_28
|
||||
# 1035| r0_30(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1035| r0_31(float) = Constant[1.0] :
|
||||
# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31
|
||||
# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1035| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
|
||||
# 1035| mu0_35(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
|
||||
# 1036| r0_36(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
|
||||
# 1036| r0_37(glval<decltype([...](...){...})>) = VariableAddress[#temp1036:20] :
|
||||
# 1036| mu0_38(decltype([...](...){...})) = Uninitialized[#temp1036:20] : &:r0_37
|
||||
# 1036| r0_39(glval<String>) = FieldAddress[s] : r0_37
|
||||
#-----| r0_40(glval<unknown>) = FunctionAddress[String] :
|
||||
#-----| v0_41(void) = Call : func:r0_40, this:r0_39
|
||||
#-----| mu0_42(unknown) = ^CallSideEffect : ~mu0_2
|
||||
#-----| mu0_43(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_39
|
||||
# 1036| r0_44(glval<int>) = FieldAddress[x] : r0_37
|
||||
#-----| r0_45(glval<int>) = VariableAddress[x] :
|
||||
#-----| r0_46(int) = Load : &:r0_45, ~mu0_2
|
||||
#-----| mu0_47(int) = Store : &:r0_44, r0_46
|
||||
# 1036| r0_48(decltype([...](...){...})) = Load : &:r0_37, ~mu0_2
|
||||
# 1036| mu0_49(decltype([...](...){...})) = Store : &:r0_36, r0_48
|
||||
# 1037| r0_50(glval<decltype([...](...){...})>) = VariableAddress[lambda_val] :
|
||||
# 1037| r0_51(glval<decltype([...](...){...})>) = Convert : r0_50
|
||||
# 1037| r0_52(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1037| r0_53(float) = Constant[2.0] :
|
||||
# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53
|
||||
# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1037| v0_56(void) = ^BufferReadSideEffect[-1] : &:r0_51, ~mu0_2
|
||||
# 1037| mu0_57(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_51
|
||||
# 1038| r0_58(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
|
||||
# 1038| r0_59(glval<decltype([...](...){...})>) = VariableAddress[#temp1038:29] :
|
||||
# 1038| mu0_60(decltype([...](...){...})) = Uninitialized[#temp1038:29] : &:r0_59
|
||||
# 1038| r0_61(glval<String &>) = FieldAddress[s] : r0_59
|
||||
# 1038| r0_62(glval<String &>) = VariableAddress[s] :
|
||||
# 1038| r0_63(String &) = Load : &:r0_62, ~mu0_2
|
||||
# 1038| r0_64(glval<String>) = CopyValue : r0_63
|
||||
# 1038| r0_65(String &) = CopyValue : r0_64
|
||||
# 1038| mu0_66(String &) = Store : &:r0_61, r0_65
|
||||
# 1038| r0_67(decltype([...](...){...})) = Load : &:r0_59, ~mu0_2
|
||||
# 1038| mu0_68(decltype([...](...){...})) = Store : &:r0_58, r0_67
|
||||
# 1039| r0_69(glval<decltype([...](...){...})>) = VariableAddress[lambda_ref_explicit] :
|
||||
# 1039| r0_70(glval<decltype([...](...){...})>) = Convert : r0_69
|
||||
# 1039| r0_71(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1039| r0_72(float) = Constant[3.0] :
|
||||
# 1039| r0_73(char) = Call : func:r0_71, this:r0_70, 0:r0_72
|
||||
# 1039| mu0_74(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1039| v0_75(void) = ^BufferReadSideEffect[-1] : &:r0_70, ~mu0_2
|
||||
# 1039| mu0_76(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_70
|
||||
# 1040| r0_77(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
|
||||
# 1040| r0_78(glval<decltype([...](...){...})>) = VariableAddress[#temp1040:29] :
|
||||
# 1040| mu0_79(decltype([...](...){...})) = Uninitialized[#temp1040:29] : &:r0_78
|
||||
# 1040| r0_80(glval<String>) = FieldAddress[s] : r0_78
|
||||
#-----| r0_81(glval<unknown>) = FunctionAddress[String] :
|
||||
#-----| v0_82(void) = Call : func:r0_81, this:r0_80
|
||||
#-----| mu0_83(unknown) = ^CallSideEffect : ~mu0_2
|
||||
#-----| mu0_84(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_80
|
||||
# 1040| r0_85(decltype([...](...){...})) = Load : &:r0_78, ~mu0_2
|
||||
# 1040| mu0_86(decltype([...](...){...})) = Store : &:r0_77, r0_85
|
||||
# 1041| r0_87(glval<decltype([...](...){...})>) = VariableAddress[lambda_val_explicit] :
|
||||
# 1041| r0_88(glval<decltype([...](...){...})>) = Convert : r0_87
|
||||
# 1041| r0_89(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1041| r0_90(float) = Constant[4.0] :
|
||||
# 1041| r0_91(char) = Call : func:r0_89, this:r0_88, 0:r0_90
|
||||
# 1041| mu0_92(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1041| v0_93(void) = ^BufferReadSideEffect[-1] : &:r0_88, ~mu0_2
|
||||
# 1041| mu0_94(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_88
|
||||
# 1042| r0_95(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
|
||||
# 1042| r0_96(glval<decltype([...](...){...})>) = VariableAddress[#temp1042:31] :
|
||||
# 1042| mu0_97(decltype([...](...){...})) = Uninitialized[#temp1042:31] : &:r0_96
|
||||
# 1042| r0_98(glval<String &>) = FieldAddress[s] : r0_96
|
||||
# 1042| r0_99(glval<String &>) = VariableAddress[s] :
|
||||
# 1042| r0_100(String &) = Load : &:r0_99, ~mu0_2
|
||||
# 1042| r0_101(glval<String>) = CopyValue : r0_100
|
||||
# 1042| r0_102(String &) = CopyValue : r0_101
|
||||
# 1042| mu0_103(String &) = Store : &:r0_98, r0_102
|
||||
# 1042| r0_104(glval<int>) = FieldAddress[x] : r0_96
|
||||
# 1042| r0_105(glval<int>) = VariableAddress[x] :
|
||||
# 1042| r0_106(int) = Load : &:r0_105, ~mu0_2
|
||||
# 1042| mu0_107(int) = Store : &:r0_104, r0_106
|
||||
# 1042| r0_108(decltype([...](...){...})) = Load : &:r0_96, ~mu0_2
|
||||
# 1042| mu0_109(decltype([...](...){...})) = Store : &:r0_95, r0_108
|
||||
# 1043| r0_110(glval<decltype([...](...){...})>) = VariableAddress[lambda_mixed_explicit] :
|
||||
# 1043| r0_111(glval<decltype([...](...){...})>) = Convert : r0_110
|
||||
# 1043| r0_112(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1043| r0_113(float) = Constant[5.0] :
|
||||
# 1043| r0_114(char) = Call : func:r0_112, this:r0_111, 0:r0_113
|
||||
# 1043| mu0_115(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1043| v0_116(void) = ^BufferReadSideEffect[-1] : &:r0_111, ~mu0_2
|
||||
# 1043| mu0_117(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_111
|
||||
# 1044| r0_118(glval<int>) = VariableAddress[r] :
|
||||
# 1044| r0_119(glval<int>) = VariableAddress[x] :
|
||||
# 1044| r0_120(int) = Load : &:r0_119, ~mu0_2
|
||||
# 1044| r0_121(int) = Constant[1] :
|
||||
# 1044| r0_122(int) = Sub : r0_120, r0_121
|
||||
# 1044| mu0_123(int) = Store : &:r0_118, r0_122
|
||||
# 1045| r0_124(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
|
||||
# 1045| r0_125(glval<decltype([...](...){...})>) = VariableAddress[#temp1045:22] :
|
||||
# 1045| mu0_126(decltype([...](...){...})) = Uninitialized[#temp1045:22] : &:r0_125
|
||||
# 1045| r0_127(glval<String &>) = FieldAddress[s] : r0_125
|
||||
# 1045| r0_128(glval<String &>) = VariableAddress[s] :
|
||||
# 1045| r0_129(String &) = Load : &:r0_128, ~mu0_2
|
||||
# 1045| r0_130(glval<String>) = CopyValue : r0_129
|
||||
# 1045| r0_131(String &) = CopyValue : r0_130
|
||||
# 1045| mu0_132(String &) = Store : &:r0_127, r0_131
|
||||
# 1045| r0_133(glval<int>) = FieldAddress[x] : r0_125
|
||||
# 1045| r0_134(glval<int>) = VariableAddress[x] :
|
||||
# 1045| r0_135(int) = Load : &:r0_134, ~mu0_2
|
||||
# 1045| mu0_136(int) = Store : &:r0_133, r0_135
|
||||
# 1045| r0_137(glval<int>) = FieldAddress[i] : r0_125
|
||||
# 1045| r0_138(glval<int>) = VariableAddress[x] :
|
||||
# 1045| r0_139(int) = Load : &:r0_138, ~mu0_2
|
||||
# 1045| r0_140(int) = Constant[1] :
|
||||
# 1045| r0_141(int) = Add : r0_139, r0_140
|
||||
# 1045| mu0_142(int) = Store : &:r0_137, r0_141
|
||||
# 1045| r0_143(glval<int &>) = FieldAddress[j] : r0_125
|
||||
# 1045| r0_144(glval<int>) = VariableAddress[r] :
|
||||
# 1045| r0_145(int &) = CopyValue : r0_144
|
||||
# 1045| mu0_146(int &) = Store : &:r0_143, r0_145
|
||||
# 1045| r0_147(decltype([...](...){...})) = Load : &:r0_125, ~mu0_2
|
||||
# 1045| mu0_148(decltype([...](...){...})) = Store : &:r0_124, r0_147
|
||||
# 1046| r0_149(glval<decltype([...](...){...})>) = VariableAddress[lambda_inits] :
|
||||
# 1046| r0_150(glval<decltype([...](...){...})>) = Convert : r0_149
|
||||
# 1046| r0_151(glval<unknown>) = FunctionAddress[operator()] :
|
||||
# 1046| r0_152(float) = Constant[6.0] :
|
||||
# 1046| r0_153(char) = Call : func:r0_151, this:r0_150, 0:r0_152
|
||||
# 1046| mu0_154(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1046| v0_155(void) = ^BufferReadSideEffect[-1] : &:r0_150, ~mu0_2
|
||||
# 1046| mu0_156(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_150
|
||||
# 1047| v0_157(void) = NoOp :
|
||||
# 1031| v0_158(void) = ReturnVoid :
|
||||
# 1031| v0_159(void) = UnmodeledUse : mu*
|
||||
# 1031| v0_160(void) = AliasedUse : ~mu0_2
|
||||
# 1031| v0_161(void) = ExitFunction :
|
||||
|
||||
# 1032| char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::operator()(float) const
|
||||
# 1032| Block 0
|
||||
@@ -5267,25 +5220,6 @@ ir.cpp:
|
||||
# 1038| v0_23(void) = AliasedUse : ~mu0_2
|
||||
# 1038| v0_24(void) = ExitFunction :
|
||||
|
||||
# 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&)
|
||||
# 1040| Block 0
|
||||
# 1040| v0_0(void) = EnterFunction :
|
||||
# 1040| mu0_1(unknown) = AliasedDefinition :
|
||||
# 1040| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 1040| r0_3(glval<decltype([...](...){...})>) = InitializeThis :
|
||||
#-----| r0_4(glval<lambda [] type at line 1040, col. 30 &&>) = VariableAddress[p#0] :
|
||||
#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4
|
||||
# 1040| r0_6(glval<String>) = FieldAddress[s] : r0_3
|
||||
# 1040| r0_7(glval<unknown>) = FunctionAddress[String] :
|
||||
# 1040| v0_8(void) = Call : func:r0_7, this:r0_6
|
||||
# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 1040| mu0_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_6
|
||||
# 1040| v0_11(void) = NoOp :
|
||||
# 1040| v0_12(void) = ReturnVoid :
|
||||
# 1040| v0_13(void) = UnmodeledUse : mu*
|
||||
# 1040| v0_14(void) = AliasedUse : ~mu0_2
|
||||
# 1040| v0_15(void) = ExitFunction :
|
||||
|
||||
# 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~<unnamed>()
|
||||
# 1040| Block 0
|
||||
# 1040| v0_0(void) = EnterFunction :
|
||||
|
||||
@@ -884,73 +884,66 @@ ssa.cpp:
|
||||
# 213| m0_1(unknown) = AliasedDefinition :
|
||||
# 213| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 214| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
|
||||
# 214| m0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
|
||||
# 214| r0_5(glval<char[1]>) = StringConstant[""] :
|
||||
# 214| r0_6(char[1]) = Load : &:r0_5, ~m0_1
|
||||
# 214| m0_7(char[1]) = Store : &:r0_3, r0_6
|
||||
# 214| m0_8(char[32]) = Chi : total:m0_4, partial:m0_7
|
||||
# 214| r0_9(unknown[31]) = Constant[0] :
|
||||
# 214| r0_10(int) = Constant[1] :
|
||||
# 214| r0_11(glval<char>) = PointerAdd[1] : r0_3, r0_10
|
||||
# 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9
|
||||
# 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12
|
||||
# 215| r0_14(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 215| r0_15(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 215| r0_16(char[4]) = Load : &:r0_15, ~m0_1
|
||||
# 215| m0_17(char[4]) = Store : &:r0_14, r0_16
|
||||
# 216| r0_18(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 216| r0_19(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 216| r0_20(char[5]) = Load : &:r0_19, ~m0_1
|
||||
# 216| m0_21(char[5]) = Store : &:r0_18, r0_20
|
||||
# 217| r0_22(glval<char[2]>) = VariableAddress[b] :
|
||||
# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22
|
||||
# 218| r0_24(glval<char[2]>) = VariableAddress[c] :
|
||||
# 218| m0_25(char[2]) = Uninitialized[c] : &:r0_24
|
||||
# 218| r0_26(int) = Constant[0] :
|
||||
# 218| r0_27(glval<char>) = PointerAdd[1] : r0_24, r0_26
|
||||
# 218| r0_28(unknown[2]) = Constant[0] :
|
||||
# 218| m0_29(unknown[2]) = Store : &:r0_27, r0_28
|
||||
# 219| r0_30(glval<char[2]>) = VariableAddress[d] :
|
||||
# 219| m0_31(char[2]) = Uninitialized[d] : &:r0_30
|
||||
# 219| r0_32(int) = Constant[0] :
|
||||
# 219| r0_33(glval<char>) = PointerAdd[1] : r0_30, r0_32
|
||||
# 219| r0_34(char) = Constant[0] :
|
||||
# 219| m0_35(char) = Store : &:r0_33, r0_34
|
||||
# 219| m0_36(char[2]) = Chi : total:m0_31, partial:m0_35
|
||||
# 219| r0_37(int) = Constant[1] :
|
||||
# 219| r0_38(glval<char>) = PointerAdd[1] : r0_30, r0_37
|
||||
# 219| r0_39(char) = Constant[0] :
|
||||
# 219| m0_40(char) = Store : &:r0_38, r0_39
|
||||
# 219| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40
|
||||
# 220| r0_42(glval<char[2]>) = VariableAddress[e] :
|
||||
# 220| m0_43(char[2]) = Uninitialized[e] : &:r0_42
|
||||
# 220| r0_44(int) = Constant[0] :
|
||||
# 220| r0_45(glval<char>) = PointerAdd[1] : r0_42, r0_44
|
||||
# 220| r0_46(char) = Constant[0] :
|
||||
# 220| m0_47(char) = Store : &:r0_45, r0_46
|
||||
# 220| m0_48(char[2]) = Chi : total:m0_43, partial:m0_47
|
||||
# 220| r0_49(int) = Constant[1] :
|
||||
# 220| r0_50(glval<char>) = PointerAdd[1] : r0_42, r0_49
|
||||
# 220| r0_51(char) = Constant[1] :
|
||||
# 220| m0_52(char) = Store : &:r0_50, r0_51
|
||||
# 220| m0_53(char[2]) = Chi : total:m0_48, partial:m0_52
|
||||
# 221| r0_54(glval<char[3]>) = VariableAddress[f] :
|
||||
# 221| m0_55(char[3]) = Uninitialized[f] : &:r0_54
|
||||
# 221| r0_56(int) = Constant[0] :
|
||||
# 221| r0_57(glval<char>) = PointerAdd[1] : r0_54, r0_56
|
||||
# 221| r0_58(char) = Constant[0] :
|
||||
# 221| m0_59(char) = Store : &:r0_57, r0_58
|
||||
# 221| m0_60(char[3]) = Chi : total:m0_55, partial:m0_59
|
||||
# 221| r0_61(int) = Constant[1] :
|
||||
# 221| r0_62(glval<char>) = PointerAdd[1] : r0_54, r0_61
|
||||
# 221| r0_63(unknown[2]) = Constant[0] :
|
||||
# 221| m0_64(unknown[2]) = Store : &:r0_62, r0_63
|
||||
# 221| m0_65(char[3]) = Chi : total:m0_60, partial:m0_64
|
||||
# 222| v0_66(void) = NoOp :
|
||||
# 213| v0_67(void) = ReturnVoid :
|
||||
# 213| v0_68(void) = UnmodeledUse : mu*
|
||||
# 213| v0_69(void) = AliasedUse : ~m0_1
|
||||
# 213| v0_70(void) = ExitFunction :
|
||||
# 214| r0_4(glval<char[32]>) = StringConstant[""] :
|
||||
# 214| r0_5(char[32]) = Load : &:r0_4, ~m0_1
|
||||
# 214| m0_6(char[32]) = Store : &:r0_3, r0_5
|
||||
# 215| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 215| r0_8(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 215| r0_9(char[4]) = Load : &:r0_8, ~m0_1
|
||||
# 215| m0_10(char[4]) = Store : &:r0_7, r0_9
|
||||
# 216| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 216| r0_12(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 216| r0_13(char[5]) = Load : &:r0_12, ~m0_1
|
||||
# 216| m0_14(char[5]) = Store : &:r0_11, r0_13
|
||||
# 217| r0_15(glval<char[2]>) = VariableAddress[b] :
|
||||
# 217| m0_16(char[2]) = Uninitialized[b] : &:r0_15
|
||||
# 218| r0_17(glval<char[2]>) = VariableAddress[c] :
|
||||
# 218| m0_18(char[2]) = Uninitialized[c] : &:r0_17
|
||||
# 218| r0_19(int) = Constant[0] :
|
||||
# 218| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
|
||||
# 218| r0_21(unknown[2]) = Constant[0] :
|
||||
# 218| m0_22(unknown[2]) = Store : &:r0_20, r0_21
|
||||
# 219| r0_23(glval<char[2]>) = VariableAddress[d] :
|
||||
# 219| m0_24(char[2]) = Uninitialized[d] : &:r0_23
|
||||
# 219| r0_25(int) = Constant[0] :
|
||||
# 219| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
|
||||
# 219| r0_27(char) = Constant[0] :
|
||||
# 219| m0_28(char) = Store : &:r0_26, r0_27
|
||||
# 219| m0_29(char[2]) = Chi : total:m0_24, partial:m0_28
|
||||
# 219| r0_30(int) = Constant[1] :
|
||||
# 219| r0_31(glval<char>) = PointerAdd[1] : r0_23, r0_30
|
||||
# 219| r0_32(char) = Constant[0] :
|
||||
# 219| m0_33(char) = Store : &:r0_31, r0_32
|
||||
# 219| m0_34(char[2]) = Chi : total:m0_29, partial:m0_33
|
||||
# 220| r0_35(glval<char[2]>) = VariableAddress[e] :
|
||||
# 220| m0_36(char[2]) = Uninitialized[e] : &:r0_35
|
||||
# 220| r0_37(int) = Constant[0] :
|
||||
# 220| r0_38(glval<char>) = PointerAdd[1] : r0_35, r0_37
|
||||
# 220| r0_39(char) = Constant[0] :
|
||||
# 220| m0_40(char) = Store : &:r0_38, r0_39
|
||||
# 220| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40
|
||||
# 220| r0_42(int) = Constant[1] :
|
||||
# 220| r0_43(glval<char>) = PointerAdd[1] : r0_35, r0_42
|
||||
# 220| r0_44(char) = Constant[1] :
|
||||
# 220| m0_45(char) = Store : &:r0_43, r0_44
|
||||
# 220| m0_46(char[2]) = Chi : total:m0_41, partial:m0_45
|
||||
# 221| r0_47(glval<char[3]>) = VariableAddress[f] :
|
||||
# 221| m0_48(char[3]) = Uninitialized[f] : &:r0_47
|
||||
# 221| r0_49(int) = Constant[0] :
|
||||
# 221| r0_50(glval<char>) = PointerAdd[1] : r0_47, r0_49
|
||||
# 221| r0_51(char) = Constant[0] :
|
||||
# 221| m0_52(char) = Store : &:r0_50, r0_51
|
||||
# 221| m0_53(char[3]) = Chi : total:m0_48, partial:m0_52
|
||||
# 221| r0_54(int) = Constant[1] :
|
||||
# 221| r0_55(glval<char>) = PointerAdd[1] : r0_47, r0_54
|
||||
# 221| r0_56(unknown[2]) = Constant[0] :
|
||||
# 221| m0_57(unknown[2]) = Store : &:r0_55, r0_56
|
||||
# 221| m0_58(char[3]) = Chi : total:m0_53, partial:m0_57
|
||||
# 222| v0_59(void) = NoOp :
|
||||
# 213| v0_60(void) = ReturnVoid :
|
||||
# 213| v0_61(void) = UnmodeledUse : mu*
|
||||
# 213| v0_62(void) = AliasedUse : ~m0_1
|
||||
# 213| v0_63(void) = ExitFunction :
|
||||
|
||||
# 226| char StringLiteralAliasing()
|
||||
# 226| Block 0
|
||||
|
||||
@@ -848,65 +848,60 @@ ssa.cpp:
|
||||
# 213| mu0_1(unknown) = AliasedDefinition :
|
||||
# 213| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 214| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
|
||||
# 214| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3
|
||||
# 214| r0_5(glval<char[1]>) = StringConstant[""] :
|
||||
# 214| r0_6(char[1]) = Load : &:r0_5, ~mu0_2
|
||||
# 214| mu0_7(char[1]) = Store : &:r0_3, r0_6
|
||||
# 214| r0_8(unknown[31]) = Constant[0] :
|
||||
# 214| r0_9(int) = Constant[1] :
|
||||
# 214| r0_10(glval<char>) = PointerAdd[1] : r0_3, r0_9
|
||||
# 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8
|
||||
# 215| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 215| r0_13(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 215| r0_14(char[4]) = Load : &:r0_13, ~mu0_2
|
||||
# 215| m0_15(char[4]) = Store : &:r0_12, r0_14
|
||||
# 216| r0_16(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 216| r0_17(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 216| r0_18(char[5]) = Load : &:r0_17, ~mu0_2
|
||||
# 216| m0_19(char[5]) = Store : &:r0_16, r0_18
|
||||
# 217| r0_20(glval<char[2]>) = VariableAddress[b] :
|
||||
# 217| m0_21(char[2]) = Uninitialized[b] : &:r0_20
|
||||
# 218| r0_22(glval<char[2]>) = VariableAddress[c] :
|
||||
# 218| mu0_23(char[2]) = Uninitialized[c] : &:r0_22
|
||||
# 218| r0_24(int) = Constant[0] :
|
||||
# 218| r0_25(glval<char>) = PointerAdd[1] : r0_22, r0_24
|
||||
# 218| r0_26(unknown[2]) = Constant[0] :
|
||||
# 218| mu0_27(unknown[2]) = Store : &:r0_25, r0_26
|
||||
# 219| r0_28(glval<char[2]>) = VariableAddress[d] :
|
||||
# 219| mu0_29(char[2]) = Uninitialized[d] : &:r0_28
|
||||
# 219| r0_30(int) = Constant[0] :
|
||||
# 219| r0_31(glval<char>) = PointerAdd[1] : r0_28, r0_30
|
||||
# 219| r0_32(char) = Constant[0] :
|
||||
# 219| mu0_33(char) = Store : &:r0_31, r0_32
|
||||
# 219| r0_34(int) = Constant[1] :
|
||||
# 219| r0_35(glval<char>) = PointerAdd[1] : r0_28, r0_34
|
||||
# 219| r0_36(char) = Constant[0] :
|
||||
# 219| mu0_37(char) = Store : &:r0_35, r0_36
|
||||
# 220| r0_38(glval<char[2]>) = VariableAddress[e] :
|
||||
# 220| mu0_39(char[2]) = Uninitialized[e] : &:r0_38
|
||||
# 220| r0_40(int) = Constant[0] :
|
||||
# 220| r0_41(glval<char>) = PointerAdd[1] : r0_38, r0_40
|
||||
# 220| r0_42(char) = Constant[0] :
|
||||
# 220| mu0_43(char) = Store : &:r0_41, r0_42
|
||||
# 220| r0_44(int) = Constant[1] :
|
||||
# 220| r0_45(glval<char>) = PointerAdd[1] : r0_38, r0_44
|
||||
# 220| r0_46(char) = Constant[1] :
|
||||
# 220| mu0_47(char) = Store : &:r0_45, r0_46
|
||||
# 221| r0_48(glval<char[3]>) = VariableAddress[f] :
|
||||
# 221| mu0_49(char[3]) = Uninitialized[f] : &:r0_48
|
||||
# 221| r0_50(int) = Constant[0] :
|
||||
# 221| r0_51(glval<char>) = PointerAdd[1] : r0_48, r0_50
|
||||
# 221| r0_52(char) = Constant[0] :
|
||||
# 221| mu0_53(char) = Store : &:r0_51, r0_52
|
||||
# 221| r0_54(int) = Constant[1] :
|
||||
# 221| r0_55(glval<char>) = PointerAdd[1] : r0_48, r0_54
|
||||
# 221| r0_56(unknown[2]) = Constant[0] :
|
||||
# 221| mu0_57(unknown[2]) = Store : &:r0_55, r0_56
|
||||
# 222| v0_58(void) = NoOp :
|
||||
# 213| v0_59(void) = ReturnVoid :
|
||||
# 213| v0_60(void) = UnmodeledUse : mu*
|
||||
# 213| v0_61(void) = AliasedUse : ~mu0_2
|
||||
# 213| v0_62(void) = ExitFunction :
|
||||
# 214| r0_4(glval<char[32]>) = StringConstant[""] :
|
||||
# 214| r0_5(char[32]) = Load : &:r0_4, ~mu0_2
|
||||
# 214| m0_6(char[32]) = Store : &:r0_3, r0_5
|
||||
# 215| r0_7(glval<char[4]>) = VariableAddress[a_nopad] :
|
||||
# 215| r0_8(glval<char[4]>) = StringConstant["foo"] :
|
||||
# 215| r0_9(char[4]) = Load : &:r0_8, ~mu0_2
|
||||
# 215| m0_10(char[4]) = Store : &:r0_7, r0_9
|
||||
# 216| r0_11(glval<char[5]>) = VariableAddress[a_infer] :
|
||||
# 216| r0_12(glval<char[5]>) = StringConstant["blah"] :
|
||||
# 216| r0_13(char[5]) = Load : &:r0_12, ~mu0_2
|
||||
# 216| m0_14(char[5]) = Store : &:r0_11, r0_13
|
||||
# 217| r0_15(glval<char[2]>) = VariableAddress[b] :
|
||||
# 217| m0_16(char[2]) = Uninitialized[b] : &:r0_15
|
||||
# 218| r0_17(glval<char[2]>) = VariableAddress[c] :
|
||||
# 218| mu0_18(char[2]) = Uninitialized[c] : &:r0_17
|
||||
# 218| r0_19(int) = Constant[0] :
|
||||
# 218| r0_20(glval<char>) = PointerAdd[1] : r0_17, r0_19
|
||||
# 218| r0_21(unknown[2]) = Constant[0] :
|
||||
# 218| mu0_22(unknown[2]) = Store : &:r0_20, r0_21
|
||||
# 219| r0_23(glval<char[2]>) = VariableAddress[d] :
|
||||
# 219| mu0_24(char[2]) = Uninitialized[d] : &:r0_23
|
||||
# 219| r0_25(int) = Constant[0] :
|
||||
# 219| r0_26(glval<char>) = PointerAdd[1] : r0_23, r0_25
|
||||
# 219| r0_27(char) = Constant[0] :
|
||||
# 219| mu0_28(char) = Store : &:r0_26, r0_27
|
||||
# 219| r0_29(int) = Constant[1] :
|
||||
# 219| r0_30(glval<char>) = PointerAdd[1] : r0_23, r0_29
|
||||
# 219| r0_31(char) = Constant[0] :
|
||||
# 219| mu0_32(char) = Store : &:r0_30, r0_31
|
||||
# 220| r0_33(glval<char[2]>) = VariableAddress[e] :
|
||||
# 220| mu0_34(char[2]) = Uninitialized[e] : &:r0_33
|
||||
# 220| r0_35(int) = Constant[0] :
|
||||
# 220| r0_36(glval<char>) = PointerAdd[1] : r0_33, r0_35
|
||||
# 220| r0_37(char) = Constant[0] :
|
||||
# 220| mu0_38(char) = Store : &:r0_36, r0_37
|
||||
# 220| r0_39(int) = Constant[1] :
|
||||
# 220| r0_40(glval<char>) = PointerAdd[1] : r0_33, r0_39
|
||||
# 220| r0_41(char) = Constant[1] :
|
||||
# 220| mu0_42(char) = Store : &:r0_40, r0_41
|
||||
# 221| r0_43(glval<char[3]>) = VariableAddress[f] :
|
||||
# 221| mu0_44(char[3]) = Uninitialized[f] : &:r0_43
|
||||
# 221| r0_45(int) = Constant[0] :
|
||||
# 221| r0_46(glval<char>) = PointerAdd[1] : r0_43, r0_45
|
||||
# 221| r0_47(char) = Constant[0] :
|
||||
# 221| mu0_48(char) = Store : &:r0_46, r0_47
|
||||
# 221| r0_49(int) = Constant[1] :
|
||||
# 221| r0_50(glval<char>) = PointerAdd[1] : r0_43, r0_49
|
||||
# 221| r0_51(unknown[2]) = Constant[0] :
|
||||
# 221| mu0_52(unknown[2]) = Store : &:r0_50, r0_51
|
||||
# 222| v0_53(void) = NoOp :
|
||||
# 213| v0_54(void) = ReturnVoid :
|
||||
# 213| v0_55(void) = UnmodeledUse : mu*
|
||||
# 213| v0_56(void) = AliasedUse : ~mu0_2
|
||||
# 213| v0_57(void) = ExitFunction :
|
||||
|
||||
# 226| char StringLiteralAliasing()
|
||||
# 226| Block 0
|
||||
|
||||
@@ -108,7 +108,9 @@
|
||||
| captures.cpp:22:3:24:4 | declaration |
|
||||
| captures.cpp:22:8:22:15 | definition of myLambda |
|
||||
| captures.cpp:22:8:22:15 | myLambda |
|
||||
| captures.cpp:22:18:24:3 | [...](...){...} |
|
||||
| captures.cpp:22:18:24:3 | initializer for myLambda |
|
||||
| captures.cpp:22:18:24:3 | {...} |
|
||||
| captures.cpp:22:19:22:19 | (constructor) |
|
||||
| captures.cpp:22:19:22:19 | (constructor) |
|
||||
| captures.cpp:22:19:22:19 | (constructor) |
|
||||
@@ -123,8 +125,6 @@
|
||||
| captures.cpp:22:19:22:19 | operator= |
|
||||
| captures.cpp:22:19:22:19 | return ... |
|
||||
| captures.cpp:22:19:22:19 | { ... } |
|
||||
| captures.cpp:22:19:24:3 | [...](...){...} |
|
||||
| captures.cpp:22:19:24:3 | {...} |
|
||||
| captures.cpp:22:23:22:23 | definition of x |
|
||||
| captures.cpp:22:23:22:23 | x |
|
||||
| captures.cpp:22:23:22:23 | x |
|
||||
@@ -164,7 +164,9 @@
|
||||
| end_pos.cpp:9:5:11:6 | declaration |
|
||||
| end_pos.cpp:9:10:9:11 | definition of fp |
|
||||
| end_pos.cpp:9:10:9:11 | fp |
|
||||
| end_pos.cpp:9:14:11:5 | [...](...){...} |
|
||||
| end_pos.cpp:9:14:11:5 | initializer for fp |
|
||||
| end_pos.cpp:9:14:11:5 | {...} |
|
||||
| end_pos.cpp:9:15:9:15 | (constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (constructor) |
|
||||
| end_pos.cpp:9:15:9:15 | (constructor) |
|
||||
@@ -177,8 +179,6 @@
|
||||
| end_pos.cpp:9:15:9:15 | operator= |
|
||||
| end_pos.cpp:9:15:9:15 | return ... |
|
||||
| end_pos.cpp:9:15:9:15 | { ... } |
|
||||
| end_pos.cpp:9:15:11:5 | [...](...){...} |
|
||||
| end_pos.cpp:9:15:11:5 | {...} |
|
||||
| end_pos.cpp:9:17:9:17 | definition of ii |
|
||||
| end_pos.cpp:9:17:9:17 | ii |
|
||||
| end_pos.cpp:9:17:9:18 | (reference to) |
|
||||
|
||||
@@ -17,7 +17,6 @@ missingOperand
|
||||
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
|
||||
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
|
||||
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |
|
||||
|
||||
@@ -21,7 +21,6 @@ missingOperand
|
||||
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
|
||||
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
|
||||
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |
|
||||
|
||||
@@ -17,7 +17,6 @@ missingOperand
|
||||
| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() |
|
||||
| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) |
|
||||
| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) |
|
||||
| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2<int(*)(lambda::Val, lambda::Val)>(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const |
|
||||
| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() |
|
||||
|
||||
@@ -55,3 +55,9 @@ void f(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// This pattern is used to emulate C++20 concepts in a way that's very light on
|
||||
// template syntax.
|
||||
template<typename T1, typename T2>
|
||||
auto sfinaeTrick(T1 x1, T2 x2) -> decltype(x1 == x2, bool()) { // GOOD
|
||||
return x1 == x2;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
| test.c:25:5:25:16 | ... ? ... : ... | This expression has no effect. | test.c:25:5:25:16 | ... ? ... : ... | |
|
||||
| test.c:26:15:26:16 | 32 | This expression has no effect. | test.c:26:15:26:16 | 32 | |
|
||||
| test.c:27:9:27:10 | 33 | This expression has no effect. | test.c:27:9:27:10 | 33 | |
|
||||
| test.cpp:24:3:24:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | test.cpp:9:14:9:23 | operator++ | operator++ |
|
||||
| test.cpp:25:3:25:3 | call to operator++ | This expression has no effect (because $@ has no external side effects). | test.cpp:9:14:9:23 | operator++ | operator++ |
|
||||
| test.cpp:62:5:62:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:47:14:47:22 | operator= | operator= |
|
||||
| test.cpp:65:5:65:5 | call to operator= | This expression has no effect (because $@ has no external side effects). | test.cpp:55:7:55:7 | operator= | operator= |
|
||||
| volatile.c:9:5:9:5 | c | This expression has no effect. | volatile.c:9:5:9:5 | c | |
|
||||
|
||||
@@ -21,8 +21,8 @@ public:
|
||||
MyIterator arg1, arg2;
|
||||
_It arg3;
|
||||
|
||||
++arg1; // pure, does nothing
|
||||
++arg2; // pure, does nothing
|
||||
++arg1; // pure, does nothing [NOT DETECTED]
|
||||
++arg2; // pure, does nothing [NOT DETECTED]
|
||||
++arg3; // not pure in all cases (when _It is int this has a side-effect)
|
||||
|
||||
return arg2;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set |
|
||||
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set |
|
||||
| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set |
|
||||
| test3.cpp:7:32:7:62 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test3.cpp:7:32:7:62 | call to context | boost::asio::ssl::context::context | test3.cpp:7:32:7:61 | tls | tls | test3.cpp:7:32:7:62 | call to context | no_tlsv1_1 has not been set |
|
||||
| test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set |
|
||||
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set |
|
||||
| test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set |
|
||||
|
||||
@@ -65,13 +65,13 @@ void TestHardcodedProtocols()
|
||||
|
||||
////////////////////// Hardcoded algorithms
|
||||
|
||||
boost::asio::ssl::context cxt_tlsv12(boost::asio::ssl::context::tlsv12); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv12c(boost::asio::ssl::context::tlsv12_client); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv12s(boost::asio::ssl::context::tlsv12_server); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv12(boost::asio::ssl::context::tlsv12);
|
||||
boost::asio::ssl::context cxt_tlsv12c(boost::asio::ssl::context::tlsv12_client);
|
||||
boost::asio::ssl::context cxt_tlsv12s(boost::asio::ssl::context::tlsv12_server);
|
||||
|
||||
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv13c(boost::asio::ssl::context::tlsv13_client); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv13s(boost::asio::ssl::context::tlsv13_server); // BUG
|
||||
boost::asio::ssl::context cxt_tlsv13(boost::asio::ssl::context::tlsv13);
|
||||
boost::asio::ssl::context cxt_tlsv13c(boost::asio::ssl::context::tlsv13_client);
|
||||
boost::asio::ssl::context cxt_tlsv13s(boost::asio::ssl::context::tlsv13_server);
|
||||
}
|
||||
|
||||
void InterProceduralTest(boost::asio::ssl::context::method m)
|
||||
@@ -100,11 +100,11 @@ void TestHardcodedProtocols_inter()
|
||||
|
||||
////////////////////// Hardcoded algorithms
|
||||
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12_client); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12_server); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12);
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12_client);
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv12_server);
|
||||
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13_client); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13_server); // BUG
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13);
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13_client);
|
||||
InterProceduralTest(boost::asio::ssl::context::tlsv13_server);
|
||||
}
|
||||
|
||||
19
cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp
Normal file
19
cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "asio/boost_simulation.hpp"
|
||||
|
||||
// examples from the qhelp...
|
||||
|
||||
void useTLS_bad()
|
||||
{
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
|
||||
ctx.set_options(boost::asio::ssl::context::no_tlsv1); // BAD: missing no_tlsv1_1
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
void useTLS_good()
|
||||
{
|
||||
boost::asio::ssl::context ctx(boost::asio::ssl::context::tls);
|
||||
ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD
|
||||
|
||||
// ...
|
||||
}
|
||||
@@ -205,6 +205,57 @@ class VSTestAssertNonNullMethod extends AssertNonNullMethod {
|
||||
override AssertFailedExceptionClass getExceptionClass() { any() }
|
||||
}
|
||||
|
||||
/** An NUnit assertion method. */
|
||||
abstract class NUnitAssertMethod extends AssertMethod {
|
||||
override int getAssertionIndex() { result = 0 }
|
||||
|
||||
override AssertionExceptionClass getExceptionClass() { any() }
|
||||
}
|
||||
|
||||
/** An NUnit assertion method. */
|
||||
class NUnitAssertTrueMethod extends AssertTrueMethod, NUnitAssertMethod {
|
||||
NUnitAssertTrueMethod() {
|
||||
exists(NUnitAssertClass c |
|
||||
this = c.getATrueMethod()
|
||||
or
|
||||
this = c.getAnIsTrueMethod()
|
||||
or
|
||||
this = c.getAThatMethod() and
|
||||
this.getParameter(0).getType() instanceof BoolType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** An NUnit negated assertion method. */
|
||||
class NUnitAssertFalseMethod extends AssertFalseMethod, NUnitAssertMethod {
|
||||
NUnitAssertFalseMethod() {
|
||||
exists(NUnitAssertClass c |
|
||||
this = c.getAFalseMethod() or
|
||||
this = c.getAnIsFalseMethod()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** An NUnit `null` assertion method. */
|
||||
class NUnitAssertNullMethod extends AssertNullMethod, NUnitAssertMethod {
|
||||
NUnitAssertNullMethod() {
|
||||
exists(NUnitAssertClass c |
|
||||
this = c.getANullMethod() or
|
||||
this = c.getAnIsNullMethod()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** An NUnit non-`null` assertion method. */
|
||||
class NUnitAssertNonNullMethod extends AssertNonNullMethod, NUnitAssertMethod {
|
||||
NUnitAssertNonNullMethod() {
|
||||
exists(NUnitAssertClass c |
|
||||
this = c.getANotNullMethod() or
|
||||
this = c.getAnIsNotNullMethod()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A method that forwards to another assertion method. */
|
||||
class ForwarderAssertMethod extends AssertMethod {
|
||||
Assertion a;
|
||||
|
||||
@@ -117,3 +117,67 @@ class TestCaseSourceAttribute extends Attribute {
|
||||
result.getName() = this.getFieldName()
|
||||
}
|
||||
}
|
||||
|
||||
/** The `NUnit.Framework.Assert` class. */
|
||||
class NUnitAssertClass extends Class {
|
||||
NUnitAssertClass() { this.hasQualifiedName("NUnit.Framework.Assert") }
|
||||
|
||||
/** Gets a `Null(object, ...)` method. */
|
||||
Method getANullMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("Null")
|
||||
}
|
||||
|
||||
/** Gets an `IsNull(object, ...)` method. */
|
||||
Method getAnIsNullMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("IsNull")
|
||||
}
|
||||
|
||||
/** Gets a `NotNull(object, ...)` method. */
|
||||
Method getANotNullMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("NotNull")
|
||||
}
|
||||
|
||||
/** Gets an `IsNotNull(object, ...)` method. */
|
||||
Method getAnIsNotNullMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("IsNotNull")
|
||||
}
|
||||
|
||||
/** Gets a `True(bool, ...)` method. */
|
||||
Method getATrueMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("True")
|
||||
}
|
||||
|
||||
/** Gets an `IsTrue(bool, ...)` method. */
|
||||
Method getAnIsTrueMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("IsTrue")
|
||||
}
|
||||
|
||||
/** Gets a `False(bool, ...)` method. */
|
||||
Method getAFalseMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("False")
|
||||
}
|
||||
|
||||
/** Gets an `IsFalse(bool, ...)` method. */
|
||||
Method getAnIsFalseMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("IsFalse")
|
||||
}
|
||||
|
||||
/** Gets a `That(...)` method. */
|
||||
Method getAThatMethod() {
|
||||
result.getDeclaringType() = this and
|
||||
result.hasName("That")
|
||||
}
|
||||
}
|
||||
|
||||
/** The `NUnit.Framework.AssertionException` class. */
|
||||
class AssertionExceptionClass extends Class {
|
||||
AssertionExceptionClass() { this.hasQualifiedName("NUnit.Framework.AssertionException") }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
interface IPerson
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
string Greeting
|
||||
{
|
||||
get => "Hello";
|
||||
set { }
|
||||
}
|
||||
|
||||
string Greet(string name) => Greeting + " " + name;
|
||||
|
||||
string GreetingString => Greet(Name);
|
||||
|
||||
void Greet();
|
||||
}
|
||||
|
||||
class Person : IPerson
|
||||
{
|
||||
public string Name => "Petra";
|
||||
|
||||
string IPerson.Greeting { get => "Howdy"; set { } }
|
||||
|
||||
public void Greet() { }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
| DefaultInterfaceMethods.cs:9:9:9:11 | get_Greeting |
|
||||
| DefaultInterfaceMethods.cs:10:9:10:11 | set_Greeting |
|
||||
| DefaultInterfaceMethods.cs:13:12:13:16 | Greet |
|
||||
| DefaultInterfaceMethods.cs:15:30:15:40 | get_GreetingString |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import csharp
|
||||
|
||||
class DefaultInterfaceMethod extends Method {
|
||||
class DefaultInterfaceMethod extends Callable {
|
||||
DefaultInterfaceMethod() {
|
||||
this.hasBody() and
|
||||
this.getDeclaringType() instanceof Interface
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
assertTrue
|
||||
| ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:9:28:9:33 | IsTrue | ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:9:40:9:40 | b |
|
||||
| nunit.cs:28:21:28:24 | True | nunit.cs:28:31:28:39 | condition |
|
||||
| nunit.cs:29:21:29:24 | True | nunit.cs:29:31:29:39 | condition |
|
||||
| nunit.cs:31:21:31:26 | IsTrue | nunit.cs:31:33:31:41 | condition |
|
||||
| nunit.cs:32:21:32:26 | IsTrue | nunit.cs:32:33:32:41 | condition |
|
||||
| nunit.cs:52:21:52:24 | That | nunit.cs:52:31:52:39 | condition |
|
||||
| nunit.cs:53:21:53:24 | That | nunit.cs:53:31:53:39 | condition |
|
||||
| nunit.cs:54:21:54:24 | That | nunit.cs:54:31:54:39 | condition |
|
||||
assertFalse
|
||||
| ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:10:28:10:34 | IsFalse | ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:10:41:10:41 | b |
|
||||
| nunit.cs:34:21:34:25 | False | nunit.cs:34:32:34:40 | condition |
|
||||
| nunit.cs:35:21:35:25 | False | nunit.cs:35:32:35:40 | condition |
|
||||
| nunit.cs:37:21:37:27 | IsFalse | nunit.cs:37:34:37:42 | condition |
|
||||
| nunit.cs:38:21:38:27 | IsFalse | nunit.cs:38:34:38:42 | condition |
|
||||
assertNull
|
||||
| ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:7:28:7:33 | IsNull | ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:7:42:7:42 | o |
|
||||
| nunit.cs:40:21:40:24 | Null | nunit.cs:40:33:40:40 | anObject |
|
||||
| nunit.cs:41:21:41:24 | Null | nunit.cs:41:33:41:40 | anObject |
|
||||
| nunit.cs:43:21:43:26 | IsNull | nunit.cs:43:35:43:42 | anObject |
|
||||
| nunit.cs:44:21:44:26 | IsNull | nunit.cs:44:35:44:42 | anObject |
|
||||
assertNonNull
|
||||
| ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:8:28:8:36 | IsNotNull | ../../../resources/stubs/Microsoft.VisualStudio.TestTools.UnitTesting.cs:8:45:8:45 | o |
|
||||
| nunit.cs:46:21:46:27 | NotNull | nunit.cs:46:36:46:43 | anObject |
|
||||
| nunit.cs:47:21:47:27 | NotNull | nunit.cs:47:36:47:43 | anObject |
|
||||
| nunit.cs:49:21:49:29 | IsNotNull | nunit.cs:49:38:49:45 | anObject |
|
||||
| nunit.cs:50:21:50:29 | IsNotNull | nunit.cs:50:38:50:45 | anObject |
|
||||
18
csharp/ql/test/library-tests/frameworks/test/Assertions.ql
Normal file
18
csharp/ql/test/library-tests/frameworks/test/Assertions.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.commons.Assertions
|
||||
|
||||
query predicate assertTrue(AssertTrueMethod m, Parameter p) {
|
||||
m.fromSource() and m.fromSource() and p = m.getAssertedParameter()
|
||||
}
|
||||
|
||||
query predicate assertFalse(AssertFalseMethod m, Parameter p) {
|
||||
m.fromSource() and m.fromSource() and p = m.getAssertedParameter()
|
||||
}
|
||||
|
||||
query predicate assertNull(AssertNullMethod m, Parameter p) {
|
||||
m.fromSource() and m.fromSource() and p = m.getAssertedParameter()
|
||||
}
|
||||
|
||||
query predicate assertNonNull(AssertNonNullMethod m, Parameter p) {
|
||||
m.fromSource() and m.fromSource() and p = m.getAssertedParameter()
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
| nunit.cs:52:55:52:55 | n | nunit.cs:44:26:44:31 | Source |
|
||||
| nunit.cs:57:78:57:78 | n | nunit.cs:33:26:33:31 | Source |
|
||||
| nunit.cs:85:55:85:55 | n | nunit.cs:77:26:77:31 | Source |
|
||||
| nunit.cs:90:78:90:78 | n | nunit.cs:66:26:66:31 | Source |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| nunit.cs:62:21:62:25 | Test3 | nunit.cs:49:18:49:26 | TestCases |
|
||||
| nunit.cs:67:21:67:25 | Test4 | nunit.cs:38:18:38:26 | TestCases |
|
||||
| nunit.cs:72:21:72:25 | Test5 | nunit.cs:76:18:76:34 | PropertyTestCases |
|
||||
| nunit.cs:95:21:95:25 | Test3 | nunit.cs:82:18:82:26 | TestCases |
|
||||
| nunit.cs:100:21:100:25 | Test4 | nunit.cs:71:18:71:26 | TestCases |
|
||||
| nunit.cs:105:21:105:25 | Test5 | nunit.cs:109:18:109:34 | PropertyTestCases |
|
||||
|
||||
@@ -14,20 +14,20 @@
|
||||
| XUnit.cs:30:21:30:25 | Test2 | TestMethod | CallableOrCFE |
|
||||
| XUnit.cs:30:21:30:25 | Test2 | TestMethod | InstanceCallable |
|
||||
| XUnit.cs:30:21:30:25 | Test2 | TestMethod | XUnitTestMethod |
|
||||
| nunit.cs:42:11:42:21 | MyTestSuite | TestClass | LeafType |
|
||||
| nunit.cs:42:11:42:21 | MyTestSuite | TestClass | NUnitFixture |
|
||||
| nunit.cs:52:21:52:25 | Test1 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:52:21:52:25 | Test1 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:52:21:52:25 | Test1 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:57:21:57:25 | Test2 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:57:21:57:25 | Test2 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:57:21:57:25 | Test2 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:62:21:62:25 | Test3 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:62:21:62:25 | Test3 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:62:21:62:25 | Test3 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:67:21:67:25 | Test4 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:67:21:67:25 | Test4 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:67:21:67:25 | Test4 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:72:21:72:25 | Test5 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:72:21:72:25 | Test5 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:72:21:72:25 | Test5 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:75:11:75:21 | MyTestSuite | TestClass | LeafType |
|
||||
| nunit.cs:75:11:75:21 | MyTestSuite | TestClass | NUnitFixture |
|
||||
| nunit.cs:85:21:85:25 | Test1 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:85:21:85:25 | Test1 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:85:21:85:25 | Test1 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:90:21:90:25 | Test2 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:90:21:90:25 | Test2 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:90:21:90:25 | Test2 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:95:21:95:25 | Test3 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:95:21:95:25 | Test3 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:95:21:95:25 | Test3 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:100:21:100:25 | Test4 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:100:21:100:25 | Test4 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:100:21:100:25 | Test4 | TestMethod | NUnitTestMethod |
|
||||
| nunit.cs:105:21:105:25 | Test5 | TestMethod | CallableOrCFE |
|
||||
| nunit.cs:105:21:105:25 | Test5 | TestMethod | InstanceCallable |
|
||||
| nunit.cs:105:21:105:25 | Test5 | TestMethod | NUnitTestMethod |
|
||||
|
||||
@@ -22,6 +22,39 @@ namespace NUnit.Framework
|
||||
class TestAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
class Assert
|
||||
{
|
||||
public void True(bool condition) { }
|
||||
public void True(bool condition, string message, params object[] parms) { }
|
||||
|
||||
public void IsTrue(bool condition) { }
|
||||
public void IsTrue(bool condition, string message, params object[] parms) { }
|
||||
|
||||
public void False(bool condition) { }
|
||||
public void False(bool condition, string message, params object[] parms) { }
|
||||
|
||||
public void IsFalse(bool condition) { }
|
||||
public void IsFalse(bool condition, string message, params object[] parms) { }
|
||||
|
||||
public void Null(object anObject) { }
|
||||
public void Null(object anObject, string message, params object[] parms) { }
|
||||
|
||||
public void IsNull(object anObject) { }
|
||||
public void IsNull(object anObject, string message, params object[] parms) { }
|
||||
|
||||
public void NotNull(object anObject) { }
|
||||
public void NotNull(object anObject, string message, params object[] parms) { }
|
||||
|
||||
public void IsNotNull(object anObject) { }
|
||||
public void IsNotNull(object anObject, string message, params object[] parms) { }
|
||||
|
||||
public void That(bool condition) { }
|
||||
public void That(bool condition, string message, params object[] parms) { }
|
||||
public void That(bool condition, Func<string> getExceptionMessage) { }
|
||||
}
|
||||
|
||||
public class AssertionException : Exception { }
|
||||
}
|
||||
|
||||
namespace NUnitTests
|
||||
|
||||
@@ -3,7 +3,7 @@ Introduction to QL
|
||||
|
||||
QL is the powerful query language that underlies CodeQL, which is used to analyze code.
|
||||
Queries written with CodeQL can find errors and uncover variants of important security vulnerabilities.
|
||||
Visit Semmle's `security research page <https://lgtm.com/security>`__ to read about examples of vulnerabilities that we have recently found in open source projects.
|
||||
Visit `GitHub Security Lab <https://securitylab.github.com/>`__ to read about examples of vulnerabilities that we have recently found in open source projects.
|
||||
|
||||
Before diving into code analysis with CodeQL, it can be helpful to learn about the underlying language more generally.
|
||||
|
||||
|
||||
@@ -175,11 +175,13 @@ Ambient nodes are mostly ignored by control flow and data flow analysis. The out
|
||||
Static type information
|
||||
-----------------------
|
||||
|
||||
.. TODO: Remove link to QL command-line tools below?
|
||||
Static type information and global name binding is available for projects with "full" TypeScript extraction enabled. This option is enabled by default for projects on LGTM.com and when you create databases with the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__.
|
||||
|
||||
Static type information and global name binding is available for projects with "full" TypeScript extraction enabled. This option is enabled by default for projects on LGTM.com. If you are using the `QL command-line tools <https://help.semmle.com/wiki/display/SD/QL+command-line+tools>`__, you must enable it by passing ``--typescript-full`` to the JavaScript extractor. For further information on customizing calls to the extractor, see `Customizing JavaScript extraction <https://help.semmle.com/wiki/display/SD/Customizing+JavaScript+extraction>`__.
|
||||
.. pull-quote:: Note
|
||||
|
||||
**Note:** Without full extraction, the classes and predicates described in this section are empty.
|
||||
If you are using the `legacy QL command-line tools <https://help.semmle.com/wiki/display/SD/QL+command-line+tools>`__, you must enable full TypeScript extraction by passing ``--typescript-full`` to the JavaScript extractor. For further information on customizing calls to the extractor, see `Customizing JavaScript extraction <https://help.semmle.com/wiki/display/SD/Customizing+JavaScript+extraction>`__.
|
||||
|
||||
Without full extraction, the classes and predicates described in this section are empty.
|
||||
|
||||
Basic usage
|
||||
~~~~~~~~~~~
|
||||
|
||||
@@ -10,17 +10,15 @@ Queries are programs written with CodeQL. They are designed to highlight issues
|
||||
- **Path queries**: queries that describe the flow of information between a source and a sink in your code.
|
||||
- **Metric queries**: queries that compute statistics for your code.
|
||||
|
||||
You can add custom queries to `custom query packs <https://lgtm.com/help/lgtm/about-queries#what-are-query-packs>`__ to analyze your projects in `LGTM <https://lgtm.com>`__, use them to analyze a project using the `command-line tools <https://help.semmle.com/wiki/display/SD/QL+command-line+tools>`__, or you can contribute to the standard CodeQL queries in our `open source repository on GitHub <https://github.com/semmle/ql>`__.
|
||||
|
||||
.. TODO: Change "command-line tools" to a link to the CodeQL CLI? Similarly, change "QL for Eclipse".
|
||||
You can add custom queries to `custom query packs <https://lgtm.com/help/lgtm/about-queries#what-are-query-packs>`__ to analyze your projects in `LGTM <https://lgtm.com>`__, use them to analyze a database with the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__, or you can contribute to the standard CodeQL queries in our `open source repository on GitHub <https://github.com/semmle/ql>`__.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
Note
|
||||
|
||||
Only the results generated by alert and path queries are displayed on LGTM.
|
||||
You can display the results generated by metric queries by running them against your project in the `query console on LGTM <https://lgtm.com/query>`__ or in `QL for Eclipse <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/home-page.html>`__.
|
||||
You can explore the paths generated by path queries `directly in LGTM <https://lgtm.com/help/lgtm/exploring-data-flow-paths>`__ and the `path explorer view <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/path-explorer-view.html>`__ in QL for Eclipse.
|
||||
You can display the results generated by metric queries by running them against your project in the `query console on LGTM <https://lgtm.com/query>`__ or with the CodeQL `extension for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__.
|
||||
You can explore the paths generated by path queries `directly in LGTM <https://lgtm.com/help/lgtm/exploring-data-flow-paths>`__ and in the `Results view <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__ in VS Code.
|
||||
|
||||
|
||||
This topic is a basic introduction to structuring query files. You can find further information on writing queries for specific programming languages `here <https://help.semmle.com/QL/learn-ql/>`__, and detailed technical information about QL in the `QL language handbook <https://help.semmle.com/QL/ql-handbook/index.html>`__ and the `QL language specification <https://help.semmle.com/QL/ql-spec/language.html>`__.
|
||||
@@ -54,15 +52,15 @@ Query metadata
|
||||
Query metadata is used to identify your custom queries when they are added to the GitHub repository or used in your analysis. Metadata provides information about the query's purpose, and also specifies how to interpret and display the query results. For a full list of metadata properties, see the :doc:`query metadata reference <query-metadata>`. The exact metadata requirement depends on how you are going to run your query:
|
||||
|
||||
- If you are contributing a query to the GitHub repository, please read the `query metadata style guide <https://github.com/Semmle/ql/blob/master/docs/query-metadata-style-guide.md#metadata-area>`__.
|
||||
- If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis <https://lgtm.com/help/lgtm/writing-custom-queries>`__.
|
||||
- If you are analyzing a project using the `QL command-line tools <https://help.semmle.com/wiki/display/SD/QL+command-line+tools>`__, see `Preparing custom queries <https://help.semmle.com/wiki/display/SD/Preparing+custom+queries>`__.
|
||||
- If you are running a query in the query console on LGTM or in the Quick query window in QL for Eclipse, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct `@kind` property, as explained below. See `Using the query console <https://lgtm.com/help/lgtm/using-query-console>`__ and `Running a quick query <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/run-quick-query.html>`__ for further information.
|
||||
- If you are adding a custom query to a query pack for analysis using LGTM , see `Writing custom queries to include in LGTM analysis <https://lgtm.com/help/lgtm/writing-custom-queries>`__.
|
||||
- If you are analyzing a database using the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__, your query metadata must contain ``@kind``.
|
||||
- If you are running a query in the query console on LGTM or with the CodeQL extension for VS Code, metadata is not mandatory. However, if you want your results to be displayed as either an 'alert' or a 'path', you must specify the correct ``@kind`` property, as explained below. See `Using the query console <https://lgtm.com/help/lgtm/using-query-console>`__ and `Using the extension <https://help.semmle.com/codeql/codeql-for-vscode/procedures/using-extension.html>`__ for further information.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
Note
|
||||
|
||||
Queries that are contributed to the open source repository, added to a query pack in LGTM, or used to analyze a project with the QL command-line tools must have a query type (``@kind``) specified. The ``@kind`` property indicates how to interpret and display the results of the query analysis:
|
||||
Queries that are contributed to the open source repository, added to a query pack in LGTM, or used to analyze a database with the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__ must have a query type (``@kind``) specified. The ``@kind`` property indicates how to interpret and display the results of the query analysis:
|
||||
|
||||
- Alert query metadata must contain ``@kind problem``.
|
||||
- Path query metadata must contain ``@kind path-problem``.
|
||||
@@ -87,7 +85,7 @@ When writing your own alert queries, you would typically import the standard lib
|
||||
|
||||
There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. See :doc:`Constructing path queries <path-queries>` for further information.
|
||||
|
||||
You can explore the contents of all the standard libraries in the `CodeQL library reference documentation <https://help.semmle.com/QL/ql-libraries.html>`__, using `QL for Eclipse <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/z-queries.html>`__, or in the `GitHub repository <https://github.com/semmle/ql>`__.
|
||||
You can explore the contents of all the standard libraries in the `CodeQL library reference documentation <https://help.semmle.com/QL/ql-libraries.html>`__ or in the `GitHub repository <https://github.com/semmle/ql>`__.
|
||||
|
||||
|
||||
Optional CodeQL classes and predicates
|
||||
|
||||
@@ -14,7 +14,7 @@ This topic provides information on how to structure a path query file so you can
|
||||
|
||||
Note
|
||||
|
||||
The alerts generated by path queries are displayed by default in `LGTM <https://lgtm.com>`__ and included in the results generated using the `QL command-line tools <https://help.semmle.com/wiki/display/SD/QL+command-line+tools>`__. You can also view the paths explanations generated by your path query `directly in LGTM <https://lgtm.com/help/lgtm/exploring-data-flow-paths>`__, or using the `Path explorer view <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/path-explorer-view.html>`__ in `QL for Eclipse <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/home-page.html>`__.
|
||||
The alerts generated by path queries are displayed by default in `LGTM <https://lgtm.com>`__ and included in the results generated using the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__. You can also view the path explanations generated by your path query `directly in LGTM <https://lgtm.com/help/lgtm/exploring-data-flow-paths>`__ or in the CodeQL `extension for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__.
|
||||
|
||||
|
||||
To learn more about modeling data flow with CodeQL, see :doc:`Introduction to data flow <../intro-to-data-flow>`.
|
||||
@@ -181,7 +181,7 @@ Select clauses for path queries consist of four 'columns', with the following st
|
||||
select element, source, sink, string
|
||||
|
||||
The ``element`` and ``string`` columns represent the location of the alert and the alert message respectively, as explained in :doc:`Introduction to writing queries <introduction-to-queries>`. The second and third columns, ``source`` and ``sink``, are nodes on the path graph selected by the query.
|
||||
Each result generated by your query is displayed at a single location in the same way as an alert query. Additionally, each result also has an associated path, which can be viewed in LGTM, or the `path explorer view <https://help.semmle.com/ql-for-eclipse/Content/WebHelp/path-explorer-view.html>`__ in QL for Eclipse.
|
||||
Each result generated by your query is displayed at a single location in the same way as an alert query. Additionally, each result also has an associated path, which can be viewed in LGTM or in the CodeQL `extension for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__.
|
||||
|
||||
The ``element`` that you select in the first column depends on the purpose of the query and the type of issue that it is designed to find. This is particularly important for security issues. For example, if you believe the ``source`` value to be globally invalid or malicious it may be best to display the alert at the ``source``. In contrast, you should consider displaying the alert at the ``sink`` if you believe it is the element that requires sanitization.
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ Query metadata
|
||||
==============
|
||||
|
||||
Any query that is run as part of an analysis includes a number of properties, known as query metadata. Metadata is included at the top of each query file as the content of a `QLDoc <https://help.semmle.com/QL/ql-spec/qldoc.html>`__ comment.
|
||||
For alerts and path queries, this metadata tells LGTM and QL for Eclipse how to handle the query and display its results correctly.
|
||||
For alerts and path queries, this metadata tells LGTM and the CodeQL `extension for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__ how to handle the query and display its results correctly.
|
||||
It also gives other users information about what the query results mean. For further information on query metadata, see the `query metadata style guide <https://github.com/Semmle/ql/blob/master/docs/query-metadata-style-guide.md#metadata-area>`__ in our `open source repository <https://github.com/semmle/ql>`__ on GitHub.
|
||||
You can also add metric queries to LGTM, but the results are not shown. To see the results of metric queries, you can run them in the query console or in QL for Eclipse.
|
||||
You can also add metric queries to LGTM, but the results are not shown. To see the results of metric queries, you can run them in the query console or in `Visual Studio Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__.
|
||||
|
||||
.. pull-quote::
|
||||
|
||||
@@ -93,7 +93,7 @@ Here is the metadata for one of the standard Java queries:
|
||||
|
||||
.. |image0| image:: ../../images/query-metadata.png
|
||||
|
||||
For more examples of query metadata, see the `built-in queries <https://help.semmle.com/wiki/display/QL/Built-in+queries>`__.
|
||||
For more examples of query metadata, see the standard CodeQL queries in our `GitHub repository <https://github.com/semmle/ql>`__.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ Defining 'select' statements
|
||||
============================
|
||||
|
||||
The information contained in the results of a query is controlled by the ``select`` statement. Part of the process of developing a useful query is to make the results clear and easy for other users to understand.
|
||||
When you write your own queries in the query console or QL for Eclipse there are no constraints on what can be selected.
|
||||
However, if you want to use a query to create alerts in LGTM or generate valid analysis results using the QL command-line tools, you'll need to make the ``select`` statement report results in the required format.
|
||||
When you write your own queries in the query console or in the CodeQL `extension for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__ there are no constraints on what can be selected.
|
||||
However, if you want to use a query to create alerts in LGTM or generate valid analysis results using the `CodeQL CLI <https://help.semmle.com/codeql/codeql-cli.html>`__, you'll need to make the ``select`` statement report results in the required format.
|
||||
You must also ensure that the query has the appropriate metadata properties defined.
|
||||
This topic explains how to write your select statement to generate helpful analysis results.
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"build": "tsc --project tsconfig.json",
|
||||
"check": "tsc --noEmit --project . && tslint --project .",
|
||||
"lint": "tslint --project .",
|
||||
"lint-fix": "tslint --project . --fix"
|
||||
"lint-fix": "tslint --project . --fix",
|
||||
"watch": "tsc -p . -w --sourceMap"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "12.7.11",
|
||||
|
||||
@@ -198,7 +198,9 @@ export function augmentAst(ast: AugmentedSourceFile, code: string, project: Proj
|
||||
: null;
|
||||
let type = contextualType || typeChecker.getTypeAtLocation(node);
|
||||
if (type != null) {
|
||||
let id = typeTable.buildType(type);
|
||||
let parent = node.parent;
|
||||
let unfoldAlias = ts.isTypeAliasDeclaration(parent) && node === parent.type;
|
||||
let id = typeTable.buildType(type, unfoldAlias);
|
||||
if (id != null) {
|
||||
node.$type = id;
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ function handleOpenProjectCommand(command: OpenProjectCommand) {
|
||||
fileExists: (path: string) => fs.existsSync(path),
|
||||
readFile: ts.sys.readFile,
|
||||
};
|
||||
let config = ts.parseJsonConfigFileContent(tsConfig, parseConfigHost, basePath);
|
||||
let config = ts.parseJsonConfigFileContent(tsConfig.config, parseConfigHost, basePath);
|
||||
let project = new Project(tsConfigFilename, config, state.typeTable);
|
||||
project.load();
|
||||
|
||||
@@ -272,7 +272,9 @@ function handleOpenProjectCommand(command: OpenProjectCommand) {
|
||||
});
|
||||
|
||||
for (let typeRoot of typeRoots || []) {
|
||||
traverseTypeRoot(typeRoot, "");
|
||||
if (fs.existsSync(typeRoot) && fs.statSync(typeRoot).isDirectory()) {
|
||||
traverseTypeRoot(typeRoot, "");
|
||||
}
|
||||
}
|
||||
|
||||
for (let sourceFile of program.getSourceFiles()) {
|
||||
|
||||
@@ -92,6 +92,20 @@ function isTypeofCandidateSymbol(symbol: ts.Symbol) {
|
||||
|
||||
const signatureKinds = [ts.SignatureKind.Call, ts.SignatureKind.Construct];
|
||||
|
||||
/**
|
||||
* Bitmask of flags set on a signature, but not exposed in the public API.
|
||||
*/
|
||||
const enum InternalSignatureFlags {
|
||||
HasRestParameter = 1
|
||||
}
|
||||
|
||||
/**
|
||||
* Signature interface with some internal properties exposed.
|
||||
*/
|
||||
interface AugmentedSignature extends ts.Signature {
|
||||
flags?: InternalSignatureFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes property lookup tuples `(baseType, name, property)` as three
|
||||
* staggered arrays.
|
||||
@@ -102,6 +116,16 @@ interface PropertyLookupTable {
|
||||
propertyTypes: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes `(aliasType, underlyingType)` tuples as two staggered arrays.
|
||||
*
|
||||
* Such a tuple denotes that `aliasType` is an alias for `underlyingType`.
|
||||
*/
|
||||
interface TypeAliasTable {
|
||||
aliasTypes: number[];
|
||||
underlyingTypes: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes type signature tuples `(baseType, kind, index, signature)` as four
|
||||
* staggered arrays.
|
||||
@@ -287,6 +311,11 @@ export class TypeTable {
|
||||
propertyTypes: [],
|
||||
};
|
||||
|
||||
private typeAliases: TypeAliasTable = {
|
||||
aliasTypes: [],
|
||||
underlyingTypes: [],
|
||||
};
|
||||
|
||||
private signatureMappings: SignatureTable = {
|
||||
baseTypes: [],
|
||||
kinds: [],
|
||||
@@ -304,7 +333,7 @@ export class TypeTable {
|
||||
propertyTypes: [],
|
||||
};
|
||||
|
||||
private buildTypeWorklist: [ts.Type, number][] = [];
|
||||
private buildTypeWorklist: [ts.Type, number, boolean][] = [];
|
||||
|
||||
private expansiveTypes: Map<number, boolean> = new Map();
|
||||
|
||||
@@ -372,9 +401,9 @@ export class TypeTable {
|
||||
/**
|
||||
* Gets the canonical ID for the given type, generating a fresh ID if necessary.
|
||||
*/
|
||||
public buildType(type: ts.Type): number | null {
|
||||
public buildType(type: ts.Type, unfoldAlias: boolean): number | null {
|
||||
this.isInShallowTypeContext = false;
|
||||
let id = this.getId(type);
|
||||
let id = this.getId(type, unfoldAlias);
|
||||
this.iterateBuildTypeWorklist();
|
||||
if (id == null) return null;
|
||||
return id;
|
||||
@@ -385,7 +414,7 @@ export class TypeTable {
|
||||
*
|
||||
* Returns `null` if we do not support extraction of this type.
|
||||
*/
|
||||
public getId(type: ts.Type): number | null {
|
||||
public getId(type: ts.Type, unfoldAlias: boolean): number | null {
|
||||
if (this.typeRecursionDepth > 100) {
|
||||
// Ignore infinitely nested anonymous types, such as `{x: {x: {x: ... }}}`.
|
||||
// Such a type can't be written directly with TypeScript syntax (as it would need to be named),
|
||||
@@ -397,19 +426,19 @@ export class TypeTable {
|
||||
type = this.typeChecker.getBaseTypeOfLiteralType(type);
|
||||
}
|
||||
++this.typeRecursionDepth;
|
||||
let content = this.getTypeString(type);
|
||||
let content = this.getTypeString(type, unfoldAlias);
|
||||
--this.typeRecursionDepth;
|
||||
if (content == null) return null; // Type not supported.
|
||||
let id = this.typeIds.get(content);
|
||||
if (id == null) {
|
||||
let stringValue = this.stringifyType(type);
|
||||
let stringValue = this.stringifyType(type, unfoldAlias);
|
||||
if (stringValue == null) {
|
||||
return null; // Type not supported.
|
||||
}
|
||||
id = this.typeIds.size;
|
||||
this.typeIds.set(content, id);
|
||||
this.typeToStringValues.push(stringValue);
|
||||
this.buildTypeWorklist.push([type, id]);
|
||||
this.buildTypeWorklist.push([type, id, unfoldAlias]);
|
||||
this.typeExtractionState.push(
|
||||
this.isInShallowTypeContext ? TypeExtractionState.PendingShallow : TypeExtractionState.PendingFull);
|
||||
// If the type is the self-type for a named type (not a generic instantiation of it),
|
||||
@@ -426,20 +455,20 @@ export class TypeTable {
|
||||
this.typeExtractionState[id] = TypeExtractionState.PendingFull;
|
||||
} else if (state === TypeExtractionState.DoneShallow) {
|
||||
this.typeExtractionState[id] = TypeExtractionState.PendingFull;
|
||||
this.buildTypeWorklist.push([type, id]);
|
||||
this.buildTypeWorklist.push([type, id, unfoldAlias]);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
private stringifyType(type: ts.Type): string {
|
||||
private stringifyType(type: ts.Type, unfoldAlias: boolean): string {
|
||||
let formatFlags = unfoldAlias
|
||||
? ts.TypeFormatFlags.InTypeAlias
|
||||
: ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
|
||||
let toStringValue: string;
|
||||
// Some types can't be stringified. Just discard the type if we can't stringify it.
|
||||
try {
|
||||
toStringValue = this.typeChecker.typeToString(
|
||||
type,
|
||||
undefined,
|
||||
ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
||||
toStringValue = this.typeChecker.typeToString(type, undefined, formatFlags);
|
||||
} catch (e) {
|
||||
console.warn("Recovered from a compiler crash while stringifying a type. Discarding the type.");
|
||||
console.warn(e.stack);
|
||||
@@ -477,9 +506,9 @@ export class TypeTable {
|
||||
/**
|
||||
* Gets a string representing the kind and contents of the given type.
|
||||
*/
|
||||
private getTypeString(type: AugmentedType): string | null {
|
||||
private getTypeString(type: AugmentedType, unfoldAlias: boolean): string | null {
|
||||
// Reference to a type alias.
|
||||
if (type.aliasSymbol != null) {
|
||||
if (!unfoldAlias && type.aliasSymbol != null) {
|
||||
let tag = "reference;" + this.getSymbolId(type.aliasSymbol);
|
||||
return type.aliasTypeArguments == null
|
||||
? tag
|
||||
@@ -499,7 +528,7 @@ export class TypeTable {
|
||||
if (flags & ts.TypeFlags.TypeVariable) {
|
||||
let enclosingType = getEnclosingTypeOfThisType(type);
|
||||
if (enclosingType != null) {
|
||||
return "this;" + this.getId(enclosingType);
|
||||
return "this;" + this.getId(enclosingType, false);
|
||||
} else if (symbol.parent == null) {
|
||||
// The type variable is bound on a call signature. Only extract it by name.
|
||||
return "lextypevar;" + symbol.name;
|
||||
@@ -730,7 +759,7 @@ export class TypeTable {
|
||||
private makeTypeStringVector(tag: string, types: ReadonlyArray<ts.Type>, length = types.length): string | null {
|
||||
let hash = tag;
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let id = this.getId(types[i]);
|
||||
let id = this.getId(types[i], false);
|
||||
if (id == null) return null;
|
||||
hash += ";" + id;
|
||||
}
|
||||
@@ -748,7 +777,7 @@ export class TypeTable {
|
||||
for (let property of type.getProperties()) {
|
||||
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(property, this.arbitraryAstNode);
|
||||
if (propertyType == null) return null;
|
||||
let propertyTypeId = this.getId(propertyType);
|
||||
let propertyTypeId = this.getId(propertyType, false);
|
||||
if (propertyTypeId == null) return null;
|
||||
hash += ";p" + this.getSymbolId(property) + ';' + propertyTypeId;
|
||||
}
|
||||
@@ -761,13 +790,13 @@ export class TypeTable {
|
||||
}
|
||||
let indexType = type.getStringIndexType();
|
||||
if (indexType != null) {
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return null;
|
||||
hash += ";s" + indexTypeId;
|
||||
}
|
||||
indexType = type.getNumberIndexType();
|
||||
if (indexType != null) {
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return null;
|
||||
hash += ";i" + indexTypeId;
|
||||
}
|
||||
@@ -789,6 +818,7 @@ export class TypeTable {
|
||||
typeStrings: Array.from(this.typeIds.keys()),
|
||||
typeToStringValues: this.typeToStringValues,
|
||||
propertyLookups: this.propertyLookups,
|
||||
typeAliases: this.typeAliases,
|
||||
symbolStrings: Array.from(this.symbolIds.keys()),
|
||||
moduleMappings: this.moduleMappings,
|
||||
globalMappings: this.globalMappings,
|
||||
@@ -812,10 +842,17 @@ export class TypeTable {
|
||||
let worklist = this.buildTypeWorklist;
|
||||
let typeExtractionState = this.typeExtractionState;
|
||||
while (worklist.length > 0) {
|
||||
let [type, id] = worklist.pop();
|
||||
let [type, id, unfoldAlias] = worklist.pop();
|
||||
let isShallowContext = typeExtractionState[id] === TypeExtractionState.PendingShallow;
|
||||
if (isShallowContext && !isTypeAlwaysSafeToExpand(type)) {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneShallow;
|
||||
} else if (type.aliasSymbol != null && !unfoldAlias) {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneFull;
|
||||
let underlyingTypeId = this.getId(type, true);
|
||||
if (underlyingTypeId != null) {
|
||||
this.typeAliases.aliasTypes.push(id);
|
||||
this.typeAliases.underlyingTypes.push(underlyingTypeId);
|
||||
}
|
||||
} else {
|
||||
typeExtractionState[id] = TypeExtractionState.DoneFull;
|
||||
this.isInShallowTypeContext = isShallowContext || this.isExpansiveTypeReference(type);
|
||||
@@ -847,7 +884,7 @@ export class TypeTable {
|
||||
for (let symbol of props) {
|
||||
let propertyType = this.typeChecker.getTypeOfSymbolAtLocation(symbol, this.arbitraryAstNode);
|
||||
if (propertyType == null) continue;
|
||||
let propertyTypeId = this.getId(propertyType);
|
||||
let propertyTypeId = this.getId(propertyType, false);
|
||||
if (propertyTypeId == null) continue;
|
||||
this.propertyLookups.baseTypes.push(id);
|
||||
this.propertyLookups.names.push(symbol.name);
|
||||
@@ -879,7 +916,7 @@ export class TypeTable {
|
||||
/**
|
||||
* Returns a unique string for the given call/constructor signature.
|
||||
*/
|
||||
private getSignatureString(kind: ts.SignatureKind, signature: ts.Signature): string {
|
||||
private getSignatureString(kind: ts.SignatureKind, signature: AugmentedSignature): string {
|
||||
let parameters = signature.getParameters();
|
||||
let numberOfTypeParameters = signature.typeParameters == null
|
||||
? 0
|
||||
@@ -892,27 +929,51 @@ export class TypeTable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let returnTypeId = this.getId(signature.getReturnType());
|
||||
let hasRestParam = (signature.flags & InternalSignatureFlags.HasRestParameter) !== 0;
|
||||
let restParameterTag = '';
|
||||
if (hasRestParam) {
|
||||
if (requiredParameters === parameters.length) {
|
||||
// Do not count the rest parameter as a required parameter
|
||||
requiredParameters = parameters.length - 1;
|
||||
}
|
||||
if (parameters.length === 0) return null;
|
||||
let restParameter = parameters[parameters.length - 1];
|
||||
let restParameterType = this.typeChecker.getTypeOfSymbolAtLocation(restParameter, this.arbitraryAstNode);
|
||||
if (restParameterType == null) return null;
|
||||
let restParameterTypeId = this.getId(restParameterType, false);
|
||||
if (restParameterTypeId == null) return null;
|
||||
restParameterTag = '' + restParameterTypeId;
|
||||
}
|
||||
let returnTypeId = this.getId(signature.getReturnType(), false);
|
||||
if (returnTypeId == null) {
|
||||
return null;
|
||||
}
|
||||
let tag = `${kind};${numberOfTypeParameters};${requiredParameters};${returnTypeId}`;
|
||||
let tag = `${kind};${numberOfTypeParameters};${requiredParameters};${restParameterTag};${returnTypeId}`;
|
||||
for (let typeParameter of signature.typeParameters || []) {
|
||||
tag += ";" + typeParameter.symbol.name;
|
||||
let constraint = typeParameter.getConstraint();
|
||||
let constraintId: number;
|
||||
if (constraint == null || (constraintId = this.getId(constraint)) == null) {
|
||||
if (constraint == null || (constraintId = this.getId(constraint, false)) == null) {
|
||||
tag += ";";
|
||||
} else {
|
||||
tag += ";" + constraintId;
|
||||
}
|
||||
}
|
||||
for (let parameter of parameters) {
|
||||
for (let paramIndex = 0; paramIndex < parameters.length; ++paramIndex) {
|
||||
let parameter = parameters[paramIndex];
|
||||
let parameterType = this.typeChecker.getTypeOfSymbolAtLocation(parameter, this.arbitraryAstNode);
|
||||
if (parameterType == null) {
|
||||
return null;
|
||||
}
|
||||
let parameterTypeId = this.getId(parameterType);
|
||||
let isRestParameter = hasRestParam && (paramIndex === parameters.length - 1);
|
||||
if (isRestParameter) {
|
||||
// The type of the rest parameter is the array type, but we wish to extract the non-array type.
|
||||
if (!isTypeReference(parameterType)) return null;
|
||||
let typeArguments = parameterType.typeArguments;
|
||||
if (typeArguments == null || typeArguments.length === 0) return null;
|
||||
parameterType = typeArguments[0];
|
||||
}
|
||||
let parameterTypeId = this.getId(parameterType, false);
|
||||
if (parameterTypeId == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -946,7 +1007,7 @@ export class TypeTable {
|
||||
|
||||
private extractIndexer(baseType: number, indexType: ts.Type, table: IndexerTable) {
|
||||
if (indexType == null) return;
|
||||
let indexTypeId = this.getId(indexType);
|
||||
let indexTypeId = this.getId(indexType, false);
|
||||
if (indexTypeId == null) return;
|
||||
table.baseTypes.push(baseType);
|
||||
table.propertyTypes.push(indexTypeId);
|
||||
@@ -1017,7 +1078,7 @@ export class TypeTable {
|
||||
let selfType = this.getSelfType(type);
|
||||
if (selfType != null) {
|
||||
this.checkExpansiveness(selfType);
|
||||
let id = this.getId(selfType);
|
||||
let id = this.getId(selfType, false);
|
||||
return this.expansiveTypes.get(id);
|
||||
}
|
||||
return false;
|
||||
@@ -1086,7 +1147,7 @@ export class TypeTable {
|
||||
search(type, 0);
|
||||
|
||||
function search(type: ts.TypeReference, expansionDepth: number): number | null {
|
||||
let id = typeTable.getId(type);
|
||||
let id = typeTable.getId(type, false);
|
||||
if (id == null) return null;
|
||||
|
||||
let index = indexTable.get(id);
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,6 +19,9 @@ public class AFunction<B> {
|
||||
private final List<ITypeExpression> parameterTypes;
|
||||
private final ITypeExpression thisParameterType;
|
||||
private final List<DecoratorList> parameterDecorators;
|
||||
private final IntList optionalParameterIndices;
|
||||
|
||||
public static final IntList noOptionalParams = IntList.create(0, 0);
|
||||
|
||||
public AFunction(
|
||||
Identifier id,
|
||||
@@ -29,7 +33,8 @@ public class AFunction<B> {
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
this.id = id;
|
||||
this.params = new ArrayList<IPattern>(params.size());
|
||||
this.defaults = new ArrayList<Expression>(params.size());
|
||||
@@ -42,6 +47,7 @@ public class AFunction<B> {
|
||||
this.returnType = returnType;
|
||||
this.thisParameterType = thisParameterType;
|
||||
this.parameterDecorators = parameterDecorators;
|
||||
this.optionalParameterIndices = optionalParameterIndices;
|
||||
|
||||
IPattern rest = null;
|
||||
for (Expression param : params) {
|
||||
@@ -143,4 +149,8 @@ public class AFunction<B> {
|
||||
public List<DecoratorList> getParameterDecorators() {
|
||||
return parameterDecorators;
|
||||
}
|
||||
|
||||
public IntList getOptionalParmaeterIndices() {
|
||||
return optionalParameterIndices;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(type, loc);
|
||||
this.fn =
|
||||
new AFunction<Node>(
|
||||
@@ -39,7 +41,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
parameterTypes,
|
||||
parameterDecorators,
|
||||
returnType,
|
||||
thisParameterType);
|
||||
thisParameterType,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
public AFunctionExpression(String type, SourceLocation loc, AFunction<? extends Node> fn) {
|
||||
@@ -155,4 +158,8 @@ public abstract class AFunctionExpression extends Expression implements IFunctio
|
||||
public void setDeclaredSignatureId(int id) {
|
||||
declaredSignature = id;
|
||||
}
|
||||
|
||||
public IntList getOptionalParameterIndices() {
|
||||
return fn.getOptionalParmaeterIndices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.semmle.js.ast;
|
||||
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -21,7 +22,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
}
|
||||
|
||||
public ArrowFunctionExpression(
|
||||
@@ -32,7 +34,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
Boolean async,
|
||||
List<TypeParameter> typeParameters,
|
||||
List<ITypeExpression> parameterTypes,
|
||||
ITypeExpression returnType) {
|
||||
ITypeExpression returnType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(
|
||||
"ArrowFunctionExpression",
|
||||
loc,
|
||||
@@ -45,7 +48,8 @@ public class ArrowFunctionExpression extends AFunctionExpression {
|
||||
parameterTypes,
|
||||
Collections.emptyList(),
|
||||
returnType,
|
||||
null);
|
||||
null,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -41,7 +42,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null),
|
||||
null,
|
||||
AFunction.noOptionalParams),
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -56,7 +58,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
List<TypeParameter> typeParameters,
|
||||
List<ITypeExpression> parameterTypes,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
this(
|
||||
loc,
|
||||
new AFunction<>(
|
||||
@@ -69,7 +72,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
parameterTypes,
|
||||
Collections.emptyList(),
|
||||
returnType,
|
||||
thisParameterType),
|
||||
thisParameterType,
|
||||
optionalParameterIndices),
|
||||
hasDeclareKeyword);
|
||||
}
|
||||
|
||||
@@ -207,4 +211,8 @@ public class FunctionDeclaration extends Statement implements IFunction {
|
||||
public void setDeclaredSignatureId(int id) {
|
||||
declaredSignature = id;
|
||||
}
|
||||
|
||||
public IntList getOptionalParameterIndices() {
|
||||
return fn.getOptionalParmaeterIndices();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.semmle.js.ast;
|
||||
import com.semmle.ts.ast.DecoratorList;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,7 +28,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
}
|
||||
|
||||
public FunctionExpression(
|
||||
@@ -41,7 +43,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
List<ITypeExpression> parameterTypes,
|
||||
List<DecoratorList> parameterDecorators,
|
||||
ITypeExpression returnType,
|
||||
ITypeExpression thisParameterType) {
|
||||
ITypeExpression thisParameterType,
|
||||
IntList optionalParameterIndices) {
|
||||
super(
|
||||
"FunctionExpression",
|
||||
loc,
|
||||
@@ -54,7 +57,8 @@ public class FunctionExpression extends AFunctionExpression {
|
||||
parameterTypes,
|
||||
parameterDecorators,
|
||||
returnType,
|
||||
thisParameterType);
|
||||
thisParameterType,
|
||||
optionalParameterIndices);
|
||||
}
|
||||
|
||||
public FunctionExpression(SourceLocation loc, AFunction<? extends Node> fn) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.semmle.ts.ast.INodeWithSymbol;
|
||||
import com.semmle.ts.ast.ITypeExpression;
|
||||
import com.semmle.ts.ast.ITypedAstNode;
|
||||
import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.List;
|
||||
|
||||
/** A function declaration or expression. */
|
||||
@@ -75,4 +76,6 @@ public interface IFunction extends IStatementContainer, INodeWithSymbol, ITypedA
|
||||
public int getDeclaredSignatureId();
|
||||
|
||||
public void setDeclaredSignatureId(int id);
|
||||
|
||||
public IntList getOptionalParameterIndices();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.semmle.ts.ast.TypeParameter;
|
||||
import com.semmle.ts.ast.TypeofTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -70,6 +71,10 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntList copy(IntList list) {
|
||||
return new IntList(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssignmentExpression visit(AssignmentExpression nd, Void q) {
|
||||
return new AssignmentExpression(
|
||||
@@ -138,7 +143,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
copy(nd.getTypeParameters()),
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getThisParameterType()));
|
||||
copy(nd.getThisParameterType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -367,7 +373,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getParameterDecorators()),
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getThisParameterType()));
|
||||
copy(nd.getThisParameterType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -427,7 +434,8 @@ public class NodeCopier implements Visitor<Void, INode> {
|
||||
nd.isAsync(),
|
||||
copy(nd.getTypeParameters()),
|
||||
copy(nd.getParameterTypes()),
|
||||
copy(nd.getReturnType()));
|
||||
copy(nd.getReturnType()),
|
||||
copy(nd.getOptionalParameterIndices()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -520,7 +520,7 @@ public class ASTExtractor {
|
||||
OffsetTranslation offsets = new OffsetTranslation();
|
||||
offsets.set(0, 1); // skip the initial '/'
|
||||
regexpExtractor.extract(source.substring(1, source.lastIndexOf('/')), offsets, nd, false);
|
||||
} else if (nd.isStringLiteral() && !c.isInsideType()) {
|
||||
} else if (nd.isStringLiteral() && !c.isInsideType() && nd.getRaw().length() < 1000) {
|
||||
regexpExtractor.extract(valueString, makeStringLiteralOffsets(nd.getRaw()), nd, true);
|
||||
}
|
||||
return key;
|
||||
@@ -900,7 +900,12 @@ public class ASTExtractor {
|
||||
for (IPattern param : nd.getAllParams()) {
|
||||
scopeManager.addNames(
|
||||
scopeManager.collectDeclaredNames(param, isStrict, false, DeclKind.var));
|
||||
visit(param, key, i, IdContext.varDecl);
|
||||
Label paramKey = visit(param, key, i, IdContext.varDecl);
|
||||
|
||||
// Extract optional parameters
|
||||
if (nd.getOptionalParameterIndices().contains(i)) {
|
||||
trapwriter.addTuple("isOptionalParameterDeclaration", paramKey);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -1393,7 +1398,8 @@ public class ASTExtractor {
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
AFunction.noOptionalParams);
|
||||
String fnSrc = hasSuperClass ? "(...args) { super(...args); }" : "() {}";
|
||||
SourceLocation fnloc = fakeLoc(fnSrc, loc);
|
||||
FunctionExpression fn = new FunctionExpression(fnloc, fndef);
|
||||
|
||||
@@ -578,6 +578,11 @@ public class AutoBuild {
|
||||
for (File sourceFile : project.getSourceFiles()) {
|
||||
Path sourcePath = sourceFile.toPath();
|
||||
if (!files.contains(normalizePath(sourcePath))) continue;
|
||||
if (!FileType.TYPESCRIPT.getExtensions().contains(FileUtil.extension(sourcePath))) {
|
||||
// For the time being, skip non-TypeScript files, even if the TypeScript
|
||||
// compiler can parse them for us.
|
||||
continue;
|
||||
}
|
||||
if (!extractedFiles.contains(sourcePath)) {
|
||||
typeScriptFiles.add(sourcePath.toFile());
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Main {
|
||||
* A version identifier that should be updated every time the extractor changes in such a way that
|
||||
* it may produce different tuples for the same file under the same {@link ExtractorConfig}.
|
||||
*/
|
||||
public static final String EXTRACTOR_VERSION = "2019-10-23";
|
||||
public static final String EXTRACTOR_VERSION = "2019-11-19";
|
||||
|
||||
public static final Pattern NEWLINE = Pattern.compile("\n");
|
||||
|
||||
@@ -147,7 +147,8 @@ public class Main {
|
||||
List<File> filesToExtract = new ArrayList<>();
|
||||
for (File sourceFile : project.getSourceFiles()) {
|
||||
if (files.contains(normalizeFile(sourceFile))
|
||||
&& !extractedFiles.contains(sourceFile.getAbsoluteFile())) {
|
||||
&& !extractedFiles.contains(sourceFile.getAbsoluteFile())
|
||||
&& FileType.TYPESCRIPT.getExtensions().contains(FileUtil.extension(sourceFile))) {
|
||||
filesToExtract.add(sourceFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,6 +143,7 @@ import com.semmle.ts.ast.TypeofTypeExpr;
|
||||
import com.semmle.ts.ast.UnaryTypeExpr;
|
||||
import com.semmle.ts.ast.UnionTypeExpr;
|
||||
import com.semmle.util.collections.CollectionUtil;
|
||||
import com.semmle.util.data.IntList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -804,7 +805,8 @@ public class TypeScriptASTConverter {
|
||||
hasModifier(node, "AsyncKeyword"),
|
||||
convertChildrenNotNull(node, "typeParameters"),
|
||||
convertParameterTypes(node),
|
||||
convertChildAsType(node, "type"));
|
||||
convertChildAsType(node, "type"),
|
||||
getOptionalParameterIndices(node));
|
||||
attachDeclaredSignature(function, node);
|
||||
return function;
|
||||
}
|
||||
@@ -1063,7 +1065,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
null,
|
||||
null);
|
||||
null,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(value, node);
|
||||
attachStaticType(value, node);
|
||||
attachDeclaredSignature(value, node);
|
||||
@@ -1262,7 +1265,8 @@ public class TypeScriptASTConverter {
|
||||
typeParameters,
|
||||
paramTypes,
|
||||
returnType,
|
||||
thisParam);
|
||||
thisParam,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(function, node);
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
@@ -1291,7 +1295,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
returnType,
|
||||
thisParam);
|
||||
thisParam,
|
||||
getOptionalParameterIndices(node));
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
return function;
|
||||
@@ -1645,7 +1650,8 @@ public class TypeScriptASTConverter {
|
||||
paramTypes,
|
||||
paramDecorators,
|
||||
returnType,
|
||||
thisType);
|
||||
thisType,
|
||||
getOptionalParameterIndices(node));
|
||||
attachSymbolInformation(function, node);
|
||||
attachStaticType(function, node);
|
||||
attachDeclaredSignature(function, node);
|
||||
@@ -1890,6 +1896,18 @@ public class TypeScriptASTConverter {
|
||||
return result;
|
||||
}
|
||||
|
||||
private IntList getOptionalParameterIndices(JsonObject function) throws ParseError {
|
||||
IntList list = IntList.create(0);
|
||||
int index = -1;
|
||||
for (JsonElement param : getProperParameters(function)) {
|
||||
++index;
|
||||
if (param.getAsJsonObject().has("questionToken")) {
|
||||
list.add(index);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private List<FieldDefinition> convertParameterFields(JsonObject function) throws ParseError {
|
||||
List<FieldDefinition> result = new ArrayList<>();
|
||||
int index = -1;
|
||||
|
||||
@@ -291,10 +291,10 @@ public class TypeScriptParser {
|
||||
LogbackUtils.getLogger(AbstractProcessBuilder.class).setLevel(Level.INFO);
|
||||
String explicitPath = Env.systemEnv().get(PARSER_WRAPPER_PATH_ENV_VAR);
|
||||
String semmleDistVar = Env.systemEnv().get(Env.Var.SEMMLE_DIST.name());
|
||||
if (semmleDistVar != null && !semmleDistVar.isEmpty()) {
|
||||
parserWrapper = new File(semmleDistVar, "tools/typescript-parser-wrapper/main.js");
|
||||
} else if (explicitPath != null) {
|
||||
if (explicitPath != null) {
|
||||
parserWrapper = new File(explicitPath);
|
||||
} else if (semmleDistVar != null && !semmleDistVar.isEmpty()) {
|
||||
parserWrapper = new File(semmleDistVar, "tools/typescript-parser-wrapper/main.js");
|
||||
} else {
|
||||
throw new CatastrophicError(
|
||||
"Could not find TypeScript parser: " + Env.Var.SEMMLE_DIST.name() + " is not set.");
|
||||
|
||||
@@ -81,6 +81,7 @@ public class TypeExtractor {
|
||||
extractType(i);
|
||||
}
|
||||
extractPropertyLookups(table.getPropertyLookups());
|
||||
extractTypeAliases(table.getTypeAliases());
|
||||
for (int i = 0; i < table.getNumberOfSymbols(); ++i) {
|
||||
extractSymbol(i);
|
||||
}
|
||||
@@ -161,6 +162,19 @@ public class TypeExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
private void extractTypeAliases(JsonObject aliases) {
|
||||
JsonArray aliasTypes = aliases.get("aliasTypes").getAsJsonArray();
|
||||
JsonArray underlyingTypes = aliases.get("underlyingTypes").getAsJsonArray();
|
||||
for (int i = 0; i < aliasTypes.size(); ++i) {
|
||||
int aliasType = aliasTypes.get(i).getAsInt();
|
||||
int underlyingType = underlyingTypes.get(i).getAsInt();
|
||||
trapWriter.addTuple(
|
||||
"type_alias",
|
||||
trapWriter.globalID("type;" + aliasType),
|
||||
trapWriter.globalID("type;" + underlyingType));
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbol(int index) {
|
||||
// Format is: kind;decl;parent;name
|
||||
String[] parts = split(table.getSymbolString(index), 4);
|
||||
@@ -187,13 +201,18 @@ public class TypeExtractor {
|
||||
|
||||
private void extractSignature(int index) {
|
||||
// Format is:
|
||||
// kind;numTypeParams;requiredParams;returnType(;paramName;paramType)*
|
||||
// kind;numTypeParams;requiredParams;restParamType;returnType(;paramName;paramType)*
|
||||
String[] parts = split(table.getSignatureString(index));
|
||||
Label label = trapWriter.globalID("signature;" + index);
|
||||
int kind = Integer.parseInt(parts[0]);
|
||||
int numberOfTypeParameters = Integer.parseInt(parts[1]);
|
||||
int requiredParameters = Integer.parseInt(parts[2]);
|
||||
Label returnType = trapWriter.globalID("type;" + parts[3]);
|
||||
String restParamTypeTag = parts[3];
|
||||
if (!restParamTypeTag.isEmpty()) {
|
||||
trapWriter.addTuple(
|
||||
"signature_rest_parameter", label, trapWriter.globalID("type;" + restParamTypeTag));
|
||||
}
|
||||
Label returnType = trapWriter.globalID("type;" + parts[4]);
|
||||
trapWriter.addTuple(
|
||||
"signature_types",
|
||||
label,
|
||||
@@ -202,9 +221,9 @@ public class TypeExtractor {
|
||||
numberOfTypeParameters,
|
||||
requiredParameters);
|
||||
trapWriter.addTuple("signature_contains_type", returnType, label, -1);
|
||||
int numberOfParameters = (parts.length - 4) / 2; // includes type parameters
|
||||
int numberOfParameters = (parts.length - 5) / 2; // includes type parameters
|
||||
for (int i = 0; i < numberOfParameters; ++i) {
|
||||
int partIndex = 4 + (2 * i);
|
||||
int partIndex = 5 + (2 * i);
|
||||
String paramName = parts[partIndex];
|
||||
String paramTypeId = parts[partIndex + 1];
|
||||
if (paramTypeId.length() > 0) { // Unconstrained type parameters have an empty type ID.
|
||||
|
||||
@@ -12,6 +12,7 @@ public class TypeTable {
|
||||
private final JsonArray typeStrings;
|
||||
private final JsonArray typeToStringValues;
|
||||
private final JsonObject propertyLookups;
|
||||
private final JsonObject typeAliases;
|
||||
private final JsonArray symbolStrings;
|
||||
private final JsonObject moduleMappings;
|
||||
private final JsonObject globalMappings;
|
||||
@@ -27,6 +28,7 @@ public class TypeTable {
|
||||
this.typeStrings = typeTable.get("typeStrings").getAsJsonArray();
|
||||
this.typeToStringValues = typeTable.get("typeToStringValues").getAsJsonArray();
|
||||
this.propertyLookups = typeTable.get("propertyLookups").getAsJsonObject();
|
||||
this.typeAliases = typeTable.get("typeAliases").getAsJsonObject();
|
||||
this.symbolStrings = typeTable.get("symbolStrings").getAsJsonArray();
|
||||
this.moduleMappings = typeTable.get("moduleMappings").getAsJsonObject();
|
||||
this.globalMappings = typeTable.get("globalMappings").getAsJsonObject();
|
||||
@@ -51,6 +53,10 @@ public class TypeTable {
|
||||
return propertyLookups;
|
||||
}
|
||||
|
||||
public JsonObject getTypeAliases() {
|
||||
return typeAliases;
|
||||
}
|
||||
|
||||
public int getNumberOfTypes() {
|
||||
return typeStrings.size();
|
||||
}
|
||||
|
||||
@@ -14,47 +14,51 @@ import javascript
|
||||
* Holds if the receiver of `method` is bound.
|
||||
*/
|
||||
private predicate isBoundInMethod(MethodDeclaration method) {
|
||||
exists(DataFlow::ThisNode thiz, MethodDeclaration bindingMethod |
|
||||
exists(DataFlow::ThisNode thiz, MethodDeclaration bindingMethod, string name |
|
||||
bindingMethod.getDeclaringClass() = method.getDeclaringClass() and
|
||||
not bindingMethod.isStatic() and
|
||||
thiz.getBinder().getAstNode() = bindingMethod.getBody()
|
||||
thiz.getBinder().getAstNode() = bindingMethod.getBody() and
|
||||
name = method.getName()
|
||||
|
|
||||
// binding assignments: `this[x] = <expr>.bind(...)`
|
||||
exists(DataFlow::MethodCallNode bind, DataFlow::PropWrite w |
|
||||
// this[x] = <expr>.bind(...)
|
||||
not exists(w.getPropertyName()) or // unknown name, assume everything is bound
|
||||
w.getPropertyName() = name
|
||||
|
|
||||
w = thiz.getAPropertyWrite() and
|
||||
not exists(w.getPropertyName()) and
|
||||
bind.getMethodName() = "bind" and
|
||||
bind.flowsTo(w.getRhs())
|
||||
)
|
||||
or
|
||||
// require("auto-bind")(this)
|
||||
// library binders
|
||||
exists(string mod |
|
||||
mod = "auto-bind" or
|
||||
mod = "react-autobind"
|
||||
|
|
||||
thiz.flowsTo(DataFlow::moduleImport(mod).getACall().getArgument(0))
|
||||
)
|
||||
or
|
||||
exists(string name | name = method.getName() |
|
||||
exists(DataFlow::MethodCallNode bind |
|
||||
// this.<methodName> = <expr>.bind(...)
|
||||
bind = thiz.getAPropertySource(name) and
|
||||
bind.getMethodName() = "bind"
|
||||
) or
|
||||
// heuristic reflective binders
|
||||
exists(DataFlow::CallNode binder, string calleeName |
|
||||
(
|
||||
binder.(DataFlow::MethodCallNode).getMethodName() = calleeName or
|
||||
binder.getCalleeNode().asExpr().(VarAccess).getVariable().getName() = calleeName
|
||||
) and
|
||||
calleeName.regexpMatch("(?i).*bind.*") and
|
||||
thiz.flowsTo(binder.getAnArgument()) and
|
||||
// exclude the binding assignments
|
||||
not thiz.getAPropertySource() = binder
|
||||
|
|
||||
// `myBindAll(this)`
|
||||
binder.getNumArgument() = 1
|
||||
or
|
||||
// `myBindSome(this, [<name1>, <name2>])`
|
||||
exists(DataFlow::ArrayCreationNode names |
|
||||
names.flowsTo(binder.getAnArgument()) and
|
||||
names.getAnElement().mayHaveStringValue(name)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::MethodCallNode bindAll |
|
||||
bindAll.getMethodName() = "bindAll" and
|
||||
thiz.flowsTo(bindAll.getArgument(0))
|
||||
|
|
||||
// _.bindAll(this, <name1>)
|
||||
bindAll.getArgument(1).mayHaveStringValue(name)
|
||||
or
|
||||
// _.bindAll(this, [<name1>, <name2>])
|
||||
exists(DataFlow::ArrayCreationNode names |
|
||||
names.flowsTo(bindAll.getArgument(1)) and
|
||||
names.getAnElement().mayHaveStringValue(name)
|
||||
)
|
||||
)
|
||||
// `myBindSome(this, <name1>, <name2>)`
|
||||
binder.getAnArgument().mayHaveStringValue(name)
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -66,10 +70,10 @@ private predicate isBoundInMethod(MethodDeclaration method) {
|
||||
) and
|
||||
name.regexpMatch("(?i).*(bind|bound).*")
|
||||
|
|
||||
// @autobind
|
||||
// `@autobind`
|
||||
decoration.(Identifier).getName() = name
|
||||
or
|
||||
// @action.bound
|
||||
// `@action.bound`
|
||||
decoration.(PropAccess).getPropertyName() = name
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,38 +15,17 @@
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Holds if `rl` is a simple constant, which is bound to the result of the predicate.
|
||||
*
|
||||
* For example, `/a/g` has string value `"a"` and `/abc/` has string value `"abc"`,
|
||||
* while `/ab?/` and `/a(?=b)/` do not have a string value.
|
||||
*
|
||||
* Flags are ignored, so `/a/i` is still considered to have string value `"a"`,
|
||||
* even though it also matches `"A"`.
|
||||
*
|
||||
* Note the somewhat subtle use of monotonic aggregate semantics, which makes the
|
||||
* `strictconcat` fail if one of the children of the root is not a constant (legacy
|
||||
* semantics would simply skip such children).
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
string getStringValue(RegExpLiteral rl) {
|
||||
exists(RegExpTerm root | root = rl.getRoot() |
|
||||
result = root.(RegExpConstant).getValue()
|
||||
or
|
||||
result = strictconcat(RegExpTerm ch, int i |
|
||||
ch = root.(RegExpSequence).getChild(i)
|
||||
|
|
||||
ch.(RegExpConstant).getValue() order by i
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a predecessor of `nd` that is not an SSA phi node.
|
||||
*/
|
||||
DataFlow::Node getASimplePredecessor(DataFlow::Node nd) {
|
||||
result = nd.getAPredecessor() and
|
||||
not nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition() instanceof SsaPhiNode
|
||||
not exists(SsaDefinition ssa |
|
||||
ssa = nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition()
|
||||
|
|
||||
ssa instanceof SsaPhiNode or
|
||||
ssa instanceof SsaVariableCapture
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,37 +33,33 @@ DataFlow::Node getASimplePredecessor(DataFlow::Node nd) {
|
||||
* into a form described by regular expression `regex`.
|
||||
*/
|
||||
predicate escapingScheme(string metachar, string regex) {
|
||||
metachar = "&" and regex = "&.*;"
|
||||
metachar = "&" and regex = "&.+;"
|
||||
or
|
||||
metachar = "%" and regex = "%.*"
|
||||
metachar = "%" and regex = "%.+"
|
||||
or
|
||||
metachar = "\\" and regex = "\\\\.*"
|
||||
metachar = "\\" and regex = "\\\\.+"
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `String.prototype.replace` that replaces all instances of a pattern.
|
||||
*/
|
||||
class Replacement extends DataFlow::Node {
|
||||
RegExpLiteral pattern;
|
||||
|
||||
class Replacement extends StringReplaceCall {
|
||||
Replacement() {
|
||||
exists(DataFlow::MethodCallNode mcn | this = mcn |
|
||||
mcn.getMethodName() = "replace" and
|
||||
pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0)) and
|
||||
mcn.getNumArgument() = 2 and
|
||||
pattern.isGlobal()
|
||||
)
|
||||
isGlobal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this replacement replaces the string `input` with `output`.
|
||||
* Gets the input of this replacement.
|
||||
*/
|
||||
predicate replaces(string input, string output) {
|
||||
exists(DataFlow::MethodCallNode mcn |
|
||||
mcn = this and
|
||||
input = getStringValue(pattern) and
|
||||
output = mcn.getArgument(1).getStringValue()
|
||||
)
|
||||
DataFlow::Node getInput() {
|
||||
result = this.getReceiver()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output of this replacement.
|
||||
*/
|
||||
DataFlow::SourceNode getOutput() {
|
||||
result = this
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +94,7 @@ class Replacement extends DataFlow::Node {
|
||||
* Gets the previous replacement in this chain of replacements.
|
||||
*/
|
||||
Replacement getPreviousReplacement() {
|
||||
result = getASimplePredecessor*(this.(DataFlow::MethodCallNode).getReceiver())
|
||||
result.getOutput() = getASimplePredecessor*(getInput())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +105,9 @@ class Replacement extends DataFlow::Node {
|
||||
exists(Replacement pred | pred = this.getPreviousReplacement() |
|
||||
if pred.escapes(_, metachar)
|
||||
then result = pred
|
||||
else result = pred.getAnEarlierEscaping(metachar)
|
||||
else (
|
||||
not pred.unescapes(metachar, _) and result = pred.getAnEarlierEscaping(metachar)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -142,7 +119,9 @@ class Replacement extends DataFlow::Node {
|
||||
exists(Replacement succ | this = succ.getPreviousReplacement() |
|
||||
if succ.unescapes(metachar, _)
|
||||
then result = succ
|
||||
else result = succ.getALaterUnescaping(metachar)
|
||||
else (
|
||||
not succ.escapes(_, metachar) and result = succ.getALaterUnescaping(metachar)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,18 @@ likely to handle corner cases correctly than a custom implementation.
|
||||
Otherwise, make sure to use a regular expression with the <code>g</code> flag to ensure that
|
||||
all occurrences are replaced, and remember to escape backslashes if applicable.
|
||||
</p>
|
||||
<p>
|
||||
Note, however, that this is generally <i>not</i> sufficient for replacing multi-character strings:
|
||||
the <code>String.prototype.replace</code> method only performs one pass over the input string,
|
||||
and will not replace further instances of the string that result from earlier replacements.
|
||||
</p>
|
||||
<p>
|
||||
For example, consider the code snippet <code>s.replace(/\/\.\.\//g, "")</code>, which attempts
|
||||
to strip out all occurences of <code>/../</code> from <code>s</code>. This will not work as
|
||||
expected: for the string <code>/./.././</code>, for example, it will remove the single
|
||||
occurrence of <code>/../</code> in the middle, but the remainder of the string then becomes
|
||||
<code>/../</code>, which is another instance of the substring we were trying to remove.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
|
||||
@@ -20,36 +20,31 @@ import javascript
|
||||
string metachar() { result = "'\"\\&<>\n\r\t*|{}[]%$".charAt(_) }
|
||||
|
||||
/** Gets a string matched by `e` in a `replace` call. */
|
||||
string getAMatchedString(Expr e) {
|
||||
result = getAMatchedConstant(e.(RegExpLiteral).getRoot()).getValue()
|
||||
string getAMatchedString(DataFlow::Node e) {
|
||||
result = e.(DataFlow::RegExpLiteralNode).getRoot().getAMatchedString()
|
||||
or
|
||||
result = e.getStringValue()
|
||||
}
|
||||
|
||||
/** Gets a constant matched by `t`. */
|
||||
RegExpConstant getAMatchedConstant(RegExpTerm t) {
|
||||
result = t
|
||||
or
|
||||
result = getAMatchedConstant(t.(RegExpAlt).getAlternative())
|
||||
or
|
||||
result = getAMatchedConstant(t.(RegExpGroup).getAChild())
|
||||
or
|
||||
exists(RegExpCharacterClass recc | recc = t and not recc.isInverted() |
|
||||
result = getAMatchedConstant(recc.getAChild())
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `t` is simple, that is, a union of constants. */
|
||||
predicate isSimple(RegExpTerm t) {
|
||||
t instanceof RegExpConstant
|
||||
or
|
||||
isSimple(t.(RegExpGroup).getAChild())
|
||||
or
|
||||
(
|
||||
t instanceof RegExpAlt
|
||||
or
|
||||
t instanceof RegExpCharacterClass and not t.(RegExpCharacterClass).isInverted()
|
||||
) and
|
||||
isSimpleCharacterClass(t)
|
||||
or
|
||||
isSimpleAlt(t)
|
||||
}
|
||||
|
||||
/** Holds if `t` is a non-inverted character class that contains no ranges. */
|
||||
predicate isSimpleCharacterClass(RegExpCharacterClass t) {
|
||||
not t.isInverted() and
|
||||
forall(RegExpTerm ch | ch = t.getAChild() | isSimple(ch))
|
||||
}
|
||||
|
||||
/** Holds if `t` is an alternation of simple terms. */
|
||||
predicate isSimpleAlt(RegExpAlt t) {
|
||||
forall(RegExpTerm ch | ch = t.getAChild() | isSimple(ch))
|
||||
}
|
||||
|
||||
@@ -57,16 +52,15 @@ predicate isSimple(RegExpTerm t) {
|
||||
* Holds if `mce` is of the form `x.replace(re, new)`, where `re` is a global
|
||||
* regular expression and `new` prefixes the matched string with a backslash.
|
||||
*/
|
||||
predicate isBackslashEscape(MethodCallExpr mce, RegExpLiteral re) {
|
||||
mce.getMethodName() = "replace" and
|
||||
re.flow().(DataFlow::SourceNode).flowsToExpr(mce.getArgument(0)) and
|
||||
re.isGlobal() and
|
||||
exists(string new | new = mce.getArgument(1).getStringValue() |
|
||||
// `new` is `\$&`, `\$1` or similar
|
||||
new.regexpMatch("\\\\\\$(&|\\d)")
|
||||
predicate isBackslashEscape(StringReplaceCall mce, DataFlow::RegExpLiteralNode re) {
|
||||
mce.isGlobal() and
|
||||
re = mce.getRegExp() and
|
||||
(
|
||||
// replacement with `\$&`, `\$1` or similar
|
||||
mce.getRawReplacement().getStringValue().regexpMatch("\\\\\\$(&|\\d)")
|
||||
or
|
||||
// `new` is `\c`, where `c` is a constant matched by `re`
|
||||
new.regexpMatch("\\\\\\Q" + getAMatchedString(re) + "\\E")
|
||||
// replacement of `c` with `\c`
|
||||
exists(string c | mce.replaces(c, "\\" + c))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -78,7 +72,7 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
|
||||
nd = DataFlow::globalVarRef("JSON").getAMemberCall("stringify")
|
||||
or
|
||||
// check whether `nd` itself escapes backslashes
|
||||
exists(RegExpLiteral rel | isBackslashEscape(nd.asExpr(), rel) |
|
||||
exists(DataFlow::RegExpLiteralNode rel | isBackslashEscape(nd, rel) |
|
||||
// if it's a complex regexp, we conservatively assume that it probably escapes backslashes
|
||||
not isSimple(rel.getRoot()) or
|
||||
getAMatchedString(rel) = "\\"
|
||||
@@ -104,10 +98,8 @@ predicate allBackslashesEscaped(DataFlow::Node nd) {
|
||||
/**
|
||||
* Holds if `repl` looks like a call to "String.prototype.replace" that deliberately removes the first occurrence of `str`.
|
||||
*/
|
||||
predicate removesFirstOccurence(DataFlow::MethodCallNode repl, string str) {
|
||||
repl.getMethodName() = "replace" and
|
||||
repl.getArgument(0).getStringValue() = str and
|
||||
repl.getArgument(1).getStringValue() = ""
|
||||
predicate removesFirstOccurence(StringReplaceCall repl, string str) {
|
||||
not exists(repl.getRegExp()) and repl.replaces(str, "")
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,25 +126,30 @@ predicate isDelimiterUnwrapper(
|
||||
}
|
||||
|
||||
/*
|
||||
* Holds if `repl` is a standalone use of `String.prototype.replace` to remove a single newline.
|
||||
* Holds if `repl` is a standalone use of `String.prototype.replace` to remove a single newline,
|
||||
* dollar or percent character.
|
||||
*
|
||||
* This is often done on inputs that are known to only contain a single instance of the character,
|
||||
* such as output from a shell command that is known to end with a single newline, or strings
|
||||
* like "$1.20" or "50%".
|
||||
*/
|
||||
|
||||
predicate removesTrailingNewLine(DataFlow::MethodCallNode repl) {
|
||||
repl.getMethodName() = "replace" and
|
||||
repl.getArgument(0).mayHaveStringValue("\n") and
|
||||
repl.getArgument(1).mayHaveStringValue("") and
|
||||
not exists(DataFlow::MethodCallNode other | other.getMethodName() = "replace" |
|
||||
repl.getAMethodCall() = other or
|
||||
other.getAMethodCall() = repl
|
||||
predicate whitelistedRemoval(StringReplaceCall repl) {
|
||||
not repl.isGlobal() and
|
||||
exists(string s | s = "\n" or s = "%" or s = "$" |
|
||||
repl.replaces(s, "") and
|
||||
not exists(StringReplaceCall other |
|
||||
repl.getAMethodCall() = other or
|
||||
other.getAMethodCall() = repl
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from MethodCallExpr repl, Expr old, string msg
|
||||
from StringReplaceCall repl, DataFlow::Node old, string msg
|
||||
where
|
||||
repl.getMethodName() = "replace" and
|
||||
(old = repl.getArgument(0) or old.flow().(DataFlow::SourceNode).flowsToExpr(repl.getArgument(0))) and
|
||||
(old = repl.getArgument(0) or old = repl.getRegExp()) and
|
||||
(
|
||||
not old.(RegExpLiteral).isGlobal() and
|
||||
not repl.isGlobal() and
|
||||
msg = "This replaces only the first occurrence of " + old + "." and
|
||||
// only flag if this is likely to be a sanitizer or URL encoder or decoder
|
||||
exists(string m | m = getAMatchedString(old) |
|
||||
@@ -166,19 +163,22 @@ where
|
||||
// URL encoder
|
||||
repl.getArgument(1).getStringValue().regexpMatch(urlEscapePattern)
|
||||
)
|
||||
or
|
||||
// path sanitizer
|
||||
(m = ".." or m = "/.." or m = "../" or m = "/../")
|
||||
) and
|
||||
// don't flag replace operations in a loop
|
||||
not DataFlow::valueNode(repl.getReceiver()) = DataFlow::valueNode(repl).getASuccessor+() and
|
||||
not repl.getReceiver() = repl.getASuccessor+() and
|
||||
// dont' flag unwrapper
|
||||
not isDelimiterUnwrapper(repl.flow(), _) and
|
||||
not isDelimiterUnwrapper(_, repl.flow()) and
|
||||
// dont' flag the removal of trailing newlines
|
||||
not removesTrailingNewLine(repl.flow())
|
||||
not isDelimiterUnwrapper(repl, _) and
|
||||
not isDelimiterUnwrapper(_, repl) and
|
||||
// don't flag replacements of certain characters with whitespace
|
||||
not whitelistedRemoval(repl)
|
||||
or
|
||||
exists(RegExpLiteral rel |
|
||||
exists(DataFlow::RegExpLiteralNode rel |
|
||||
isBackslashEscape(repl, rel) and
|
||||
not allBackslashesEscaped(DataFlow::valueNode(repl)) and
|
||||
not allBackslashesEscaped(repl) and
|
||||
msg = "This does not escape backslash characters in the input."
|
||||
)
|
||||
)
|
||||
select repl.getCallee(), msg
|
||||
select repl.getCalleeNode(), msg
|
||||
|
||||
@@ -33,7 +33,9 @@ predicate benignContext(Expr e) {
|
||||
inVoidContext(e) or
|
||||
|
||||
// A return statement is often used to just end the function.
|
||||
e = any(Function f).getAReturnedExpr()
|
||||
e = any(Function f).getBody()
|
||||
or
|
||||
e = any(ReturnStmt r).getExpr()
|
||||
or
|
||||
exists(ConditionalExpr cond | cond.getABranch() = e and benignContext(cond))
|
||||
or
|
||||
@@ -42,7 +44,6 @@ predicate benignContext(Expr e) {
|
||||
exists(Expr parent | parent.getUnderlyingValue() = e and benignContext(parent))
|
||||
or
|
||||
any(VoidExpr voidExpr).getOperand() = e
|
||||
|
||||
or
|
||||
// weeds out calls inside HTML-attributes.
|
||||
e.getParent().(ExprStmt).getParent() instanceof CodeInAttribute or
|
||||
@@ -70,8 +71,8 @@ predicate benignContext(Expr e) {
|
||||
e = any(PromiseCreationCall promise).getValue().asExpr()
|
||||
}
|
||||
|
||||
predicate oneshotClosure(InvokeExpr call) {
|
||||
call.getCallee().getUnderlyingValue() instanceof ImmediatelyInvokedFunctionExpr
|
||||
predicate oneshotClosure(DataFlow::CallNode call) {
|
||||
call.getCalleeNode().asExpr().getUnderlyingValue() instanceof ImmediatelyInvokedFunctionExpr
|
||||
}
|
||||
|
||||
predicate alwaysThrows(Function f) {
|
||||
@@ -149,6 +150,12 @@ predicate voidArrayCallback(DataFlow::CallNode call, Function func) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate hasNonVoidReturnType(Function f) {
|
||||
exists(TypeAnnotation type | type = f.getReturnTypeAnnotation() |
|
||||
not type.isVoid()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides classes for working with various Deferred implementations.
|
||||
@@ -214,6 +221,7 @@ where
|
||||
not benignContext(call.getEnclosingExpr()) and
|
||||
not lastStatementHasNoEffect(func) and
|
||||
// anonymous one-shot closure. Those are used in weird ways and we ignore them.
|
||||
not oneshotClosure(call.getEnclosingExpr())
|
||||
not oneshotClosure(call) and
|
||||
not hasNonVoidReturnType(func)
|
||||
select
|
||||
call, msg, func, name
|
||||
|
||||
@@ -166,7 +166,7 @@ class Require extends CallExpr, Import {
|
||||
exists(RequireVariable req |
|
||||
this.getCallee() = req.getAnAccess() and
|
||||
// `mjs` files explicitly disallow `require`
|
||||
getFile().getExtension() != "mjs"
|
||||
not getFile().getExtension() = "mjs"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -173,6 +173,23 @@ class RegExpTerm extends Locatable, @regexpterm {
|
||||
parent.(StringLiteral).flow() instanceof RegExpPatternSource
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single string this regular-expression term matches.
|
||||
*
|
||||
* This predicate is only defined for (sequences/groups of) constant regular expressions.
|
||||
* In particular, terms involving zero-width assertions like `^` or `\b` are not considered
|
||||
* to have a constant value.
|
||||
*
|
||||
* Note that this predicate does not take flags of the enclosing regular-expression literal
|
||||
* into account.
|
||||
*/
|
||||
string getConstantValue() { none() }
|
||||
|
||||
/**
|
||||
* Gets a string that is matched by this regular-expression term.
|
||||
*/
|
||||
string getAMatchedString() { result = getConstantValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,6 +240,8 @@ class RegExpConstant extends RegExpTerm, @regexp_constant {
|
||||
predicate isCharacter() { any() }
|
||||
|
||||
override predicate isNullable() { none() }
|
||||
|
||||
override string getConstantValue() { result = getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,6 +285,8 @@ class RegExpAlt extends RegExpTerm, @regexp_alt {
|
||||
int getNumAlternative() { result = getNumChild() }
|
||||
|
||||
override predicate isNullable() { getAlternative().isNullable() }
|
||||
|
||||
override string getAMatchedString() { result = getAlternative().getAMatchedString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,6 +310,21 @@ class RegExpSequence extends RegExpTerm, @regexp_seq {
|
||||
override predicate isNullable() {
|
||||
forall(RegExpTerm child | child = getAChild() | child.isNullable())
|
||||
}
|
||||
|
||||
override string getConstantValue() {
|
||||
result = getConstantValue(0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the single string matched by the `i`th child and all following children of
|
||||
* this sequence, if any.
|
||||
*/
|
||||
private string getConstantValue(int i) {
|
||||
i = getNumChild() and
|
||||
result = ""
|
||||
or
|
||||
result = getChild(i).getConstantValue() + getConstantValue(i+1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -549,6 +585,10 @@ class RegExpGroup extends RegExpTerm, @regexp_group {
|
||||
string getName() { isNamedCapture(this, result) }
|
||||
|
||||
override predicate isNullable() { getAChild().isNullable() }
|
||||
|
||||
override string getConstantValue() { result = getAChild().getConstantValue() }
|
||||
|
||||
override string getAMatchedString() { result = getAChild().getAMatchedString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -734,6 +774,10 @@ class RegExpCharacterClass extends RegExpTerm, @regexp_char_class {
|
||||
predicate isInverted() { isInverted(this) }
|
||||
|
||||
override predicate isNullable() { none() }
|
||||
|
||||
override string getAMatchedString() {
|
||||
not isInverted() and result = getAChild().getAMatchedString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -263,3 +263,62 @@ private class IteratorExceptionStep extends DataFlow::MethodCallNode, DataFlow::
|
||||
succ = this.getExceptionalReturn()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `String.prototype.replace`.
|
||||
*
|
||||
* We heuristically include any call to a method called `replace`, provided it either
|
||||
* has exactly two arguments, or local data flow suggests that the receiver may be a string.
|
||||
*/
|
||||
class StringReplaceCall extends DataFlow::MethodCallNode {
|
||||
StringReplaceCall() {
|
||||
getMethodName() = "replace" and
|
||||
(getNumArgument() = 2 or getReceiver().mayHaveStringValue(_))
|
||||
}
|
||||
|
||||
/** Gets the regular expression passed as the first argument to `replace`, if any. */
|
||||
DataFlow::RegExpLiteralNode getRegExp() {
|
||||
result.flowsTo(getArgument(0))
|
||||
}
|
||||
|
||||
/** Gets a string that is being replaced by this call. */
|
||||
string getAReplacedString() {
|
||||
result = getRegExp().getRoot().getAMatchedString() or
|
||||
getArgument(0).mayHaveStringValue(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the second argument of this call to `replace`, which is either a string
|
||||
* or a callback.
|
||||
*/
|
||||
DataFlow::Node getRawReplacement() {
|
||||
result = getArgument(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a global replacement, that is, the first argument is a regular expression
|
||||
* with the `g` flag.
|
||||
*/
|
||||
predicate isGlobal() {
|
||||
getRegExp().isGlobal()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this call to `replace` replaces `old` with `new`.
|
||||
*/
|
||||
predicate replaces(string old, string new) {
|
||||
exists(string rawNew |
|
||||
old = getAReplacedString() and
|
||||
getRawReplacement().mayHaveStringValue(rawNew) and
|
||||
new = rawNew.replaceAll("$&", old)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::FunctionNode replacer, DataFlow::PropRead pr, DataFlow::ObjectLiteralNode map |
|
||||
replacer = getCallback(1) and
|
||||
replacer.getParameter(0).flowsToExpr(pr.getPropertyNameExpr()) and
|
||||
pr = map.getAPropertyRead() and
|
||||
pr.flowsTo(replacer.getAReturn()) and
|
||||
map.hasPropertyWrite(old, any(DataFlow::Node repl | repl.getStringValue() = new))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1816,7 +1816,7 @@ class Type extends @type {
|
||||
*
|
||||
* For example, for a type `(S & T) | U` this gets the types `S`, `T`, and `U`.
|
||||
*/
|
||||
Type unfold() {
|
||||
Type unfoldUnionAndIntersection() {
|
||||
not result instanceof UnionOrIntersectionType and
|
||||
(
|
||||
result = this
|
||||
@@ -1829,6 +1829,27 @@ class Type extends @type {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeatedly unfolds unions, intersections, and type aliases and gets any of the underlying types,
|
||||
* or this type itself if it is not a union or intersection.
|
||||
*
|
||||
* For example, the type `(S & T) | U` unfolds to `S`, `T`, and `U`.
|
||||
*
|
||||
* If this is a type alias, the alias is itself included in the result, but this is not the case for intermediate type aliases.
|
||||
* For example:
|
||||
* ```js
|
||||
* type One = number | string;
|
||||
* type Two = One | Function & {x: string};
|
||||
* One; // unfolds to number, string, and One
|
||||
* Two; // unfolds to number, string, One, Function, {x: string}, and Two
|
||||
* ```
|
||||
*/
|
||||
Type unfold() {
|
||||
result = unfoldUnionAndIntersection()
|
||||
or
|
||||
result = this.(TypeAliasReference).getAliasedType().unfoldUnionAndIntersection()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this refers to the given named type, or is declared as a subtype thereof,
|
||||
* or is a union or intersection containing such a type.
|
||||
@@ -2287,6 +2308,24 @@ class EnumLiteralType extends TypeReference {
|
||||
EnumMember getEnumMember() { result = declaration }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that refers to a type alias.
|
||||
*/
|
||||
class TypeAliasReference extends TypeReference {
|
||||
TypeAliasReference() {
|
||||
type_alias(this, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type behind the type alias.
|
||||
*
|
||||
* For example, for `type B<T> = T[][]`, this maps the type `B<number>` to `number[][]`.
|
||||
*/
|
||||
Type getAliasedType() {
|
||||
type_alias(this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An anonymous interface type, such as `{ x: number }`.
|
||||
*/
|
||||
@@ -2516,17 +2555,19 @@ class CallSignatureType extends @signature_type {
|
||||
predicate hasTypeParameters() { getNumTypeParameter() > 0 }
|
||||
|
||||
/**
|
||||
* Gets the type of the `n`th parameter of this signature.
|
||||
* Gets the type of the `n`th parameter declared in this signature.
|
||||
*
|
||||
* If the `n`th parameter is a rest parameter `...T[]`, gets type `T`.
|
||||
*/
|
||||
Type getParameter(int n) { n >= 0 and result = getChild(n + getNumTypeParameter()) }
|
||||
|
||||
/**
|
||||
* Gets the type of a parameter of this signature.
|
||||
* Gets the type of a parameter of this signature, including the rest parameter, if any.
|
||||
*/
|
||||
Type getAParameter() { result = getParameter(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters.
|
||||
* Gets the number of parameters, including the rest parameter, if any.
|
||||
*/
|
||||
int getNumParameter() { result = count(int i | exists(getParameter(i))) }
|
||||
|
||||
@@ -2538,7 +2579,7 @@ class CallSignatureType extends @signature_type {
|
||||
|
||||
/**
|
||||
* Gets the number of optional parameters, that is,
|
||||
* parameters that are marked as optional with the `?` suffix.
|
||||
* parameters that are marked as optional with the `?` suffix or is a rest parameter.
|
||||
*/
|
||||
int getNumOptionalParameter() { result = getNumParameter() - getNumRequiredParameter() }
|
||||
|
||||
@@ -2552,7 +2593,9 @@ class CallSignatureType extends @signature_type {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the `n`th parameter is declared optional with the `?` suffix.
|
||||
* Holds if the `n`th parameter is declared optional with the `?` suffix or is the rest parameter.
|
||||
*
|
||||
* Note that rest parameters are not considered optional in this sense.
|
||||
*/
|
||||
predicate isOptionalParameter(int n) {
|
||||
exists(getParameter(n)) and
|
||||
@@ -2571,6 +2614,30 @@ class CallSignatureType extends @signature_type {
|
||||
* Gets the name of a parameter of this signature.
|
||||
*/
|
||||
string getAParameterName() { result = getParameterName(_) }
|
||||
|
||||
/**
|
||||
* Holds if this signature declares a rest parameter, such as `(x: number, ...y: string[])`.
|
||||
*/
|
||||
predicate hasRestParameter() { signature_rest_parameter(this, _) }
|
||||
|
||||
/**
|
||||
* Gets the type of the rest parameter, if any.
|
||||
*
|
||||
* For example, for the signature `(...y: string[])`, this gets the type `string`.
|
||||
*/
|
||||
Type getRestParameterType() {
|
||||
hasRestParameter() and
|
||||
result = getParameter(getNumParameter() - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the rest parameter as an array, if it exists.
|
||||
*
|
||||
* For example, for the signature `(...y: string[])`, this gets the type `string[]`.
|
||||
*/
|
||||
PlainArrayType getRestParameterArrayType() {
|
||||
signature_rest_parameter(this, result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -749,6 +749,21 @@ class Parameter extends BindingPattern {
|
||||
JSDocTag getJSDocTag() {
|
||||
none() // overridden in SimpleParameter
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a parameter declared optional with the `?` token.
|
||||
*
|
||||
* Note that this does not hold for rest parameters, and does not in general
|
||||
* hold for parameters with defaults.
|
||||
*
|
||||
* For example, `x`, is declared optional below:
|
||||
* ```
|
||||
* function f(x?: number) {}
|
||||
* ```
|
||||
*/
|
||||
predicate isDeclaredOptional() {
|
||||
isOptionalParameterDeclaration(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -530,6 +530,24 @@ class ArrayLiteralNode extends DataFlow::ValueNode, DataFlow::SourceNode {
|
||||
int getSize() { result = astNode.getSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node corresponding to a regular-expression literal.
|
||||
*
|
||||
* Examples:
|
||||
* ```js
|
||||
* /https?/i
|
||||
* ```
|
||||
*/
|
||||
class RegExpLiteralNode extends DataFlow::ValueNode, DataFlow::SourceNode {
|
||||
override RegExpLiteral astNode;
|
||||
|
||||
/** Holds if this regular expression has a `g` flag. */
|
||||
predicate isGlobal() { astNode.isGlobal() }
|
||||
|
||||
/** Gets the root term of this regular expression. */
|
||||
RegExpTerm getRoot() { result = astNode.getRoot() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node corresponding to a `new Array()` or `Array()` invocation.
|
||||
*
|
||||
|
||||
@@ -659,6 +659,20 @@ module TaintTracking {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint step through the Node.JS function `util.inspect(..)`.
|
||||
*/
|
||||
class UtilInspectTaintStep extends AdditionalTaintStep, DataFlow::InvokeNode {
|
||||
UtilInspectTaintStep() {
|
||||
this = DataFlow::moduleImport("util").getAMemberCall("inspect")
|
||||
}
|
||||
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
succ = this and
|
||||
this.getAnArgument() = pred
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A conditional checking a tainted string against a regular expression, which is
|
||||
* considered to be a sanitizer for all configurations.
|
||||
|
||||
@@ -61,6 +61,15 @@ private module Console {
|
||||
if name = "assert"
|
||||
then result = getArgument([1 .. getNumArgument()])
|
||||
else result = getAnArgument()
|
||||
or
|
||||
result = getASpreadArgument()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the console logging method, e.g. "log", "error", "assert", etc.
|
||||
*/
|
||||
string getName() {
|
||||
result = name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,12 @@ abstract class ReactComponent extends ASTNode {
|
||||
result = arg0
|
||||
)
|
||||
or
|
||||
result.flowsToExpr(getStaticMethod("getDerivedStateFromProps").getAReturnedExpr())
|
||||
exists(string staticMember |
|
||||
staticMember = "getDerivedStateFromProps" or
|
||||
staticMember = "getDerivedStateFromError"
|
||||
|
|
||||
result.flowsToExpr(getStaticMethod(staticMember).getAReturnedExpr())
|
||||
)
|
||||
or
|
||||
// shouldComponentUpdate: (nextProps, nextState)
|
||||
result = DataFlow::parameterNode(getInstanceMethod("shouldComponentUpdate").getParameter(1))
|
||||
|
||||
@@ -13,7 +13,7 @@ module CleartextLogging {
|
||||
import CleartextLoggingCustomizations::CleartextLogging
|
||||
|
||||
/**
|
||||
* A dataflow tracking configuration for clear-text logging of sensitive information.
|
||||
* A taint tracking configuration for clear-text logging of sensitive information.
|
||||
*
|
||||
* This configuration identifies flows from `Source`s, which are sources of
|
||||
* sensitive data, to `Sink`s, which is an abstract class representing all
|
||||
@@ -21,27 +21,37 @@ module CleartextLogging {
|
||||
* added either by extending the relevant class, or by subclassing this configuration itself,
|
||||
* and amending the sources and sinks.
|
||||
*/
|
||||
class Configuration extends DataFlow::Configuration {
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "CleartextLogging" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel lbl) {
|
||||
source.(Source).getLabel() = lbl
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel lbl) {
|
||||
sink.(Sink).getLabel() = lbl
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) { node instanceof Barrier }
|
||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof Barrier }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
StringConcatenation::taintStep(src, trg)
|
||||
or
|
||||
exists(string name | name = "toString" or name = "valueOf" |
|
||||
src.(DataFlow::SourceNode).getAMethodCall(name) = trg
|
||||
)
|
||||
or
|
||||
override predicate isSanitizerEdge(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
succ.(DataFlow::PropRead).getBase() = pred
|
||||
}
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node trg) {
|
||||
// A taint propagating data flow edge through objects: a tainted write taints the entire object.
|
||||
exists(DataFlow::PropWrite write |
|
||||
write.getRhs() = src and
|
||||
trg.(DataFlow::SourceNode).flowsTo(write.getBase())
|
||||
)
|
||||
or
|
||||
// Taint through the arguments object.
|
||||
exists(DataFlow::CallNode call, Function f |
|
||||
src = call.getAnArgument() and
|
||||
f = call.getACallee() and
|
||||
not call.isImprecise() and
|
||||
trg.asExpr() = f.getArgumentsVariable().getAnAccess()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,39 @@ module CleartextLogging {
|
||||
abstract class Source extends DataFlow::Node {
|
||||
/** Gets a string that describes the type of this data flow source. */
|
||||
abstract string describe();
|
||||
|
||||
abstract DataFlow::FlowLabel getLabel();
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow sink for clear-text logging of sensitive information.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
abstract class Sink extends DataFlow::Node {
|
||||
DataFlow::FlowLabel getLabel() {
|
||||
result.isDataOrTaint()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A barrier for clear-text logging of sensitive information.
|
||||
*/
|
||||
abstract class Barrier extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A call to `.replace()` that seems to mask sensitive information.
|
||||
*/
|
||||
class MaskingReplacer extends Barrier, DataFlow::MethodCallNode {
|
||||
MaskingReplacer() {
|
||||
this.getCalleeName() = "replace" and
|
||||
exists(RegExpLiteral reg |
|
||||
reg = this.getArgument(0).getALocalSource().asExpr() and
|
||||
reg.isGlobal() and
|
||||
any(RegExpDot term).getLiteral() = reg
|
||||
)
|
||||
and
|
||||
exists(this.getArgument(1).getStringValue())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to a logging mechanism.
|
||||
@@ -107,6 +129,10 @@ module CleartextLogging {
|
||||
}
|
||||
|
||||
override string describe() { result = "an access to " + name }
|
||||
|
||||
override DataFlow::FlowLabel getLabel() {
|
||||
result.isData()
|
||||
}
|
||||
}
|
||||
|
||||
/** An access to a variable or property that might contain a password. */
|
||||
@@ -131,6 +157,10 @@ module CleartextLogging {
|
||||
}
|
||||
|
||||
override string describe() { result = "an access to " + name }
|
||||
|
||||
override DataFlow::FlowLabel getLabel() {
|
||||
result.isData()
|
||||
}
|
||||
}
|
||||
|
||||
/** A call that might return a password. */
|
||||
@@ -143,5 +173,33 @@ module CleartextLogging {
|
||||
}
|
||||
|
||||
override string describe() { result = "a call to " + name }
|
||||
|
||||
override DataFlow::FlowLabel getLabel() {
|
||||
result.isData()
|
||||
}
|
||||
}
|
||||
|
||||
/** An access to the sensitive object `process.env`. */
|
||||
class ProcessEnvSource extends Source {
|
||||
ProcessEnvSource() {
|
||||
this = NodeJSLib::process().getAPropertyRead("env")
|
||||
}
|
||||
|
||||
override string describe() { result = "process environment" }
|
||||
|
||||
override DataFlow::FlowLabel getLabel() {
|
||||
result.isData() or
|
||||
result instanceof PartiallySensitiveMap
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow label describing a map that might contain sensitive information in some properties.
|
||||
* Property reads on such maps where the property name is fixed is unlikely to leak sensitive information.
|
||||
*/
|
||||
class PartiallySensitiveMap extends DataFlow::FlowLabel {
|
||||
PartiallySensitiveMap() {
|
||||
this = "PartiallySensitiveMap"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,6 +520,7 @@ hasProtectedKeyword (int id: @property ref);
|
||||
hasReadonlyKeyword (int id: @property ref);
|
||||
isOptionalMember (int id: @property ref);
|
||||
hasDefiniteAssignmentAssertion (int id: @field_or_vardeclarator ref);
|
||||
isOptionalParameterDeclaration (unique int parameter: @pattern ref);
|
||||
|
||||
#keyset[constructor, param_index]
|
||||
parameter_fields(
|
||||
@@ -703,6 +704,10 @@ type_property(
|
||||
varchar(900) name: string ref,
|
||||
int propertyType: @type ref);
|
||||
|
||||
type_alias(
|
||||
unique int aliasType: @type ref,
|
||||
int underlyingType: @type ref);
|
||||
|
||||
@literaltype = @stringliteraltype | @numberliteraltype | @booleanliteraltype | @bigintliteraltype;
|
||||
@type_with_literal_value = @stringliteraltype | @numberliteraltype | @bigintliteraltype;
|
||||
type_literal_value(
|
||||
@@ -717,6 +722,11 @@ signature_types (
|
||||
int required_params: int ref
|
||||
);
|
||||
|
||||
signature_rest_parameter(
|
||||
unique int sig: @signature_type ref,
|
||||
int rest_param_arra_type: @type ref
|
||||
);
|
||||
|
||||
case @signature_type.kind of
|
||||
0 = @function_signature_type
|
||||
| 1 = @constructor_signature_type
|
||||
|
||||
@@ -8006,6 +8006,17 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>isOptionalParameterDeclaration</name>
|
||||
<cardinality>3966</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>parameter</k>
|
||||
<v>3966</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>parameter_fields</name>
|
||||
<cardinality>2693</cardinality>
|
||||
<columnsizes>
|
||||
@@ -13516,6 +13527,54 @@
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_alias</name>
|
||||
<cardinality>1386</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>aliasType</k>
|
||||
<v>1386</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>underlyingType</k>
|
||||
<v>1361</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>underlyingType</src>
|
||||
<trg>aliasType</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>aliasType</src>
|
||||
<trg>underlyingType</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_literal_value</name>
|
||||
<cardinality>31882</cardinality>
|
||||
<columnsizes>
|
||||
@@ -14222,6 +14281,54 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>signature_rest_parameter</name>
|
||||
<cardinality>19521</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>sig</k>
|
||||
<v>19521</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>rest_param_arra_type</k>
|
||||
<v>14259</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>rest_param_arra_type</src>
|
||||
<trg>sig</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>sig</src>
|
||||
<trg>rest_param_arra_type</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_contains_signature</name>
|
||||
<cardinality>87640</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -47,14 +47,39 @@ test_ExprSignature
|
||||
| tst.ts:45:15:45:15 | x | string |
|
||||
| tst.ts:46:3:46:25 | constru ... umber); | any |
|
||||
| tst.ts:46:15:46:15 | x | number |
|
||||
| tst.ts:50:3:50:36 | method( ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:50:10:50:10 | x | number |
|
||||
| tst.ts:50:24:50:24 | y | string[] |
|
||||
| tst.ts:51:4:51:4 | x | number |
|
||||
| tst.ts:51:18:51:18 | y | string[] |
|
||||
| tst.ts:52:7:52:7 | x | number |
|
||||
| tst.ts:52:21:52:21 | y | string[] |
|
||||
| tst.ts:54:3:54:34 | method2 ... ing[]); | (x: number, y: string[]): any |
|
||||
| tst.ts:54:11:54:11 | x | number |
|
||||
| tst.ts:54:22:54:22 | y | string[] |
|
||||
| tst.ts:55:3:55:32 | method3 ... tring); | (x: number, y: string): any |
|
||||
| tst.ts:55:11:55:11 | x | number |
|
||||
| tst.ts:55:22:55:22 | y | string |
|
||||
| tst.ts:59:3:59:25 | method( ... ing[]); | (...y: string[]): any |
|
||||
| tst.ts:59:13:59:13 | y | string[] |
|
||||
| tst.ts:60:7:60:7 | y | string[] |
|
||||
| tst.ts:61:10:61:10 | y | string[] |
|
||||
| tst.ts:63:3:63:23 | method2 ... ing[]); | (y: string[]): any |
|
||||
| tst.ts:63:11:63:11 | y | string[] |
|
||||
| tst.ts:64:3:64:21 | method3(y: string); | (y: string): any |
|
||||
| tst.ts:64:11:64:11 | y | string |
|
||||
test_TypeReferenceSig
|
||||
| Callable | function | 0 | (x: number): string |
|
||||
| Newable | constructor | 0 | new (x: number): any |
|
||||
| OnlyRestParams | constructor | 0 | new (...y: string[]): any |
|
||||
| OnlyRestParams | function | 0 | (...y: string[]): any |
|
||||
| OverloadedCallable | function | 0 | (x: number): number |
|
||||
| OverloadedCallable | function | 1 | (x: string): string |
|
||||
| OverloadedCallable | function | 2 | (x: any): any |
|
||||
| OverloadedNewable | constructor | 0 | new (x: number): OverloadedNewable |
|
||||
| OverloadedNewable | constructor | 1 | new (x: any): any |
|
||||
| WithRestParams | constructor | 0 | new (x: number, ...y: string[]): any |
|
||||
| WithRestParams | function | 0 | (x: number, ...y: string[]): any |
|
||||
test_FunctionCallSig
|
||||
| tst.ts:2:3:2:22 | (x: number): string; | (x: number): string |
|
||||
| tst.ts:6:3:6:22 | (x: number): number; | (x: number): number |
|
||||
@@ -72,3 +97,62 @@ test_FunctionCallSig
|
||||
| tst.ts:40:1:42:1 | functio ... oo");\\n} | (g: Generic<string>): string |
|
||||
| tst.ts:45:3:45:25 | constru ... tring); | new (x: string): C |
|
||||
| tst.ts:46:3:46:25 | constru ... umber); | new (x: number): C |
|
||||
| tst.ts:50:3:50:36 | method( ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:51:3:51:30 | (x: num ... ing[]); | (x: number, ...y: string[]): any |
|
||||
| tst.ts:52:3:52:33 | new(x: ... ing[]); | new (x: number, ...y: string[]): any |
|
||||
| tst.ts:54:3:54:34 | method2 ... ing[]); | (x: number, y: string[]): any |
|
||||
| tst.ts:55:3:55:32 | method3 ... tring); | (x: number, y: string): any |
|
||||
| tst.ts:59:3:59:25 | method( ... ing[]); | (...y: string[]): any |
|
||||
| tst.ts:60:3:60:19 | (...y: string[]); | (...y: string[]): any |
|
||||
| tst.ts:61:3:61:22 | new(...y: string[]); | new (...y: string[]): any |
|
||||
| tst.ts:63:3:63:23 | method2 ... ing[]); | (y: string[]): any |
|
||||
| tst.ts:64:3:64:21 | method3(y: string); | (y: string): any |
|
||||
test_getRestParameterType
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | string \| ConcatArray<string> |
|
||||
| (...items: ConcatArray<string>[]): string[] | ConcatArray<string> |
|
||||
| (...items: string[]): number | string |
|
||||
| (...strings: string[]): string | string |
|
||||
| (...y: string[]): any | string |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | string |
|
||||
| (substring: string, ...args: any[]): string | any |
|
||||
| (x: number, ...y: string[]): any | string |
|
||||
| new (...y: string[]): any | string |
|
||||
| new (x: number, ...y: string[]): any | string |
|
||||
test_getRestParameterArray
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | (string \| ConcatArray<string>)[] |
|
||||
| (...items: ConcatArray<string>[]): string[] | ConcatArray<string>[] |
|
||||
| (...items: string[]): number | string[] |
|
||||
| (...strings: string[]): string | string[] |
|
||||
| (...y: string[]): any | string[] |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | string[] |
|
||||
| (substring: string, ...args: any[]): string | any[] |
|
||||
| (x: number, ...y: string[]): any | string[] |
|
||||
| new (...y: string[]): any | string[] |
|
||||
| new (x: number, ...y: string[]): any | string[] |
|
||||
test_RestSig_getParameter
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | 0 | items | string \| ConcatArray<string> |
|
||||
| (...items: ConcatArray<string>[]): string[] | 0 | items | ConcatArray<string> |
|
||||
| (...items: string[]): number | 0 | items | string |
|
||||
| (...strings: string[]): string | 0 | strings | string |
|
||||
| (...y: string[]): any | 0 | y | string |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 0 | start | number |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 1 | deleteCount | number |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 2 | items | string |
|
||||
| (substring: string, ...args: any[]): string | 0 | substring | string |
|
||||
| (substring: string, ...args: any[]): string | 1 | args | any |
|
||||
| (x: number, ...y: string[]): any | 0 | x | number |
|
||||
| (x: number, ...y: string[]): any | 1 | y | string |
|
||||
| new (...y: string[]): any | 0 | y | string |
|
||||
| new (x: number, ...y: string[]): any | 0 | x | number |
|
||||
| new (x: number, ...y: string[]): any | 1 | y | string |
|
||||
test_RestSig_numRequiredParams
|
||||
| (...items: (string \| ConcatArray<string>)[]): string[] | 0 |
|
||||
| (...items: ConcatArray<string>[]): string[] | 0 |
|
||||
| (...items: string[]): number | 0 |
|
||||
| (...strings: string[]): string | 0 |
|
||||
| (...y: string[]): any | 0 |
|
||||
| (start: number, deleteCount: number, ...items: string[]): string[] | 2 |
|
||||
| (substring: string, ...args: any[]): string | 1 |
|
||||
| (x: number, ...y: string[]): any | 1 |
|
||||
| new (...y: string[]): any | 0 |
|
||||
| new (x: number, ...y: string[]): any | 1 |
|
||||
|
||||
@@ -20,3 +20,22 @@ query predicate test_TypeReferenceSig(TypeReference type, SignatureKind kind, in
|
||||
query predicate test_FunctionCallSig(Function f, CallSignatureType sig) {
|
||||
sig = f.getCallSignature()
|
||||
}
|
||||
|
||||
query Type test_getRestParameterType(CallSignatureType sig) {
|
||||
result = sig.getRestParameterType()
|
||||
}
|
||||
|
||||
query Type test_getRestParameterArray(CallSignatureType sig) {
|
||||
result = sig.getRestParameterArrayType()
|
||||
}
|
||||
|
||||
query predicate test_RestSig_getParameter(CallSignatureType sig, int n, string name, Type type) {
|
||||
sig.hasRestParameter() and
|
||||
name = sig.getParameterName(n) and
|
||||
type = sig.getParameter(n)
|
||||
}
|
||||
|
||||
query int test_RestSig_numRequiredParams(CallSignatureType sig) {
|
||||
sig.hasRestParameter() and
|
||||
result = sig.getNumRequiredParameter()
|
||||
}
|
||||
|
||||
@@ -45,3 +45,21 @@ declare class C {
|
||||
constructor(x: string);
|
||||
constructor(x: number);
|
||||
}
|
||||
|
||||
interface WithRestParams {
|
||||
method(x: number, ...y: string[]);
|
||||
(x: number, ...y: string[]);
|
||||
new(x: number, ...y: string[]);
|
||||
|
||||
method2(x: number, y: string[]);
|
||||
method3(x: number, y: string);
|
||||
}
|
||||
|
||||
interface OnlyRestParams {
|
||||
method(...y: string[]);
|
||||
(...y: string[]);
|
||||
new(...y: string[]);
|
||||
|
||||
method2(y: string[]);
|
||||
method3(y: string);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
exprType
|
||||
| tst.ts:1:5:1:16 | stringOrNUll | string \| null |
|
||||
| tst.ts:2:5:2:21 | stringOrUndefined | string \| undefined |
|
||||
| tst.ts:3:5:3:27 | stringO ... defined | string \| null \| undefined |
|
||||
| tst.ts:4:5:4:16 | stringOrVoid | string \| void |
|
||||
| tst.ts:7:5:7:21 | stringOrNullAlias | string \| null |
|
||||
| tst.ts:8:5:8:32 | stringO ... defined | string \| null \| undefined |
|
||||
| tst.ts:10:5:10:23 | arrayOfStringOrNull | (string \| null)[] |
|
||||
unaliasedType
|
||||
@@ -0,0 +1,5 @@
|
||||
import javascript
|
||||
|
||||
query Type exprType(Expr e) { result = e.getType() }
|
||||
|
||||
query Type unaliasedType(TypeAliasReference ref) { result = ref.getAliasedType() }
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"include": ["."],
|
||||
"compilerOptions": {
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user