diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c0714571fc..e074b1c2079 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to QL +# Contributing to CodeQL We welcome contributions to our standard library and standard checks. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! @@ -9,13 +9,13 @@ Before we accept your pull request, we require that you have agreed to our Contr If you have an idea for a query that you would like to share with other Semmle users, please open a pull request to add it to this repository. Follow the steps below to help other users understand what your query does, and to ensure that your query is consistent with the other Semmle queries. -1. **Consult the QL documentation for query writers** +1. **Consult the documentation for query writers** - There is lots of useful documentation to help you write QL, ranging from information about query file structure to language-specific tutorials. For more information on the documentation available, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). + There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). -2. **Format your QL correctly** +2. **Format your code correctly** - All of Semmle's standard QL queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all QL contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). + All of Semmle's standard queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). 3. **Make sure your query has the correct metadata** @@ -29,7 +29,7 @@ Follow the steps below to help other users understand what your query does, and The `select` statement of your query must be compatible with the query type (determined by the `@kind` metadata property) for alert or path results to be displayed correctly in LGTM and QL for Eclipse. For more information on `select` statement format, see [Introduction to query files](https://help.semmle.com/QL/learn-ql/writing-queries/introduction-to-queries.html#select-clause) on help.semmle.com. -5. **Save your query in a `.ql` file in correct language directory in this repository** +5. **Save your query in a `.ql` file in the correct language directory in this repository** There are five language-specific directories in this repository: @@ -54,7 +54,7 @@ repositories, which might be made public. We might also use this information to contact you in relation to your contributions, as well as in the normal course of software development. We also store records of your CLA agreements. Under GDPR legislation, we do this -on the basis of our legitimate interest in creating the QL product. +on the basis of our legitimate interest in creating the CodeQL product. Please do get in touch (privacy@semmle.com) if you have any questions about this or our data protection policies. diff --git a/README.md b/README.md index b483d29cae2..3c73253b6df 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# Semmle QL +# CodeQL -This open source repository contains the standard QL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. +This open source repository contains the standard CodeQL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. -## How do I learn QL and run queries? +## How do I learn CodeQL and run queries? -There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing QL. -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. +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. ## Contributing -We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your QL for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. +We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. ## License -The QL queries in this repository are licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). +The code in this repository is licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index f22436f55cb..9a78476a2c5 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,6 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. | ## Changes to existing queries @@ -23,8 +24,10 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. | | Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. | | Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. | +| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. | +| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | More correct results and fewer false positive results | This query now understands explicitly specified argument numbers in format strings, such as the `1$` in `%1$s`. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to @@ -54,3 +57,8 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. lead to regressions (or improvements) in how queries are optimized because optimization in QL relies on static size estimates, and the control-flow edge relations will now have different size estimates than before. +* Support has been added for non-type template arguments. This means that the + return type of `Declaration::getTemplateArgument()` and + `Declaration::getATemplateArgument` have changed to `Locatable`. See the + documentation for `Declaration::getTemplateArgument()` and + `Declaration::getTemplateArgumentKind()` for details. diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index df11c0c4abc..65f99b63c3c 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -9,7 +9,9 @@ The following changes in version 1.23 affect C# analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. | +| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security, external/cwe/cwe-502 | Finds flow of untrusted input to calls to unsafe deserializers. | | Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. | +| Unsafe deserializer (`cs/unsafe-deserialization`) | security, external/cwe/cwe-502 | Finds calls to unsafe deserializers. | | Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. | ## Changes to existing queries @@ -25,7 +27,7 @@ The following changes in version 1.23 affect C# analysis in all applications. * `nameof` expressions are now extracted correctly when the name is a namespace. -## Changes to QL libraries +## Changes to libraries * The new class `NamespaceAccess` models accesses to namespaces, for example in `nameof` expressions. * The data-flow library now makes it easier to specify barriers/sanitizers diff --git a/change-notes/1.23/analysis-java.md b/change-notes/1.23/analysis-java.md index b81b681aac5..8c38f57e9d2 100644 --- a/change-notes/1.23/analysis-java.md +++ b/change-notes/1.23/analysis-java.md @@ -19,7 +19,7 @@ The following changes in version 1.23 affect Java analysis in all applications. | Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. | | Useless comparison test (`java/constant-comparison`) | Fewer false positives | Additional overflow check patterns are now recognized and no longer reported. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 7864e7627d8..3a43309f750 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -2,7 +2,9 @@ ## General improvements -* Suppor for `globalThis` has been added. +* Automatic classification of generated and minified files has been improved, in particular files generated by Doxygen are now recognized. + +* Support for `globalThis` has been added. * Support for the following frameworks and libraries has been improved: - [firebase](https://www.npmjs.com/package/firebase) @@ -14,8 +16,6 @@ * TypeScript 3.6 and 3.7 features are now supported. -* Automatic classification of generated files has been improved, in particular files generated by Doxygen are now recognized. - ## New queries | **Query** | **Tags** | **Purpose** | @@ -27,11 +27,13 @@ | Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. | | Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. | | Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. | +| Ignoring result from pure array method (`js/ignore-array-result`) | maintainability, correctness | Highlights calls to array methods without side effects where the return value is ignored. Results are shown on LGTM by default. | ## Changes to existing queries | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Double escaping or unescaping (`js/double-escaping`) | More results | This rule now detects additional escaping and unescaping functions. | | Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. | | Client-side cross-site scripting (`js/xss`) | More results, fewer false-positive results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized, and more sanitizers are detected. | | Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. | @@ -47,7 +49,7 @@ | Uncontrolled data used in path expression (`js/path-injection`) | Fewer false-positive results | This query now recognizes calls to Express `sendFile` as safe in some cases. | | Unknown directive (`js/unknown-directive`) | Fewer false positive results | This query no longer flags uses of ":", which is sometimes used like a directive. | -## Changes to QL libraries +## Changes to libraries * `Expr.getDocumentation()` now handles chain assignments. diff --git a/change-notes/1.23/analysis-python.md b/change-notes/1.23/analysis-python.md index 00fab13e098..6cea1745284 100644 --- a/change-notes/1.23/analysis-python.md +++ b/change-notes/1.23/analysis-python.md @@ -20,3 +20,8 @@ |----------------------------|------------------------|------------| | Unreachable code | Fewer false positives | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. | | `__iter__` method returns a non-iterator | Better alert message | Alert now highlights which class is expected to be an iterator. | + + +## Changes to QL libraries + +* Django library now recognizes positional arguments from a `django.conf.urls.url` regex (Django version 1.x) diff --git a/change-notes/support/README.md b/change-notes/support/README.md index 7813c69523d..f111a437183 100644 --- a/change-notes/support/README.md +++ b/change-notes/support/README.md @@ -1,6 +1,6 @@ # Files moved to ``docs`` directory -Now that all of the QL documentation is in this repository, +Now that all of the CodeQL documentation is in this repository, notes on the languages, compilers, and frameworks supported have moved. They're now stored as part of the Sphinx ``support`` project with the other documentation: ``docs/language/support``. diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql index afe49a1053b..c89ba211bbc 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql @@ -19,6 +19,7 @@ where pointlessSelfComparison(cmp) and not nanTest(cmp) and not overflowTest(cmp) and + not cmp.isFromTemplateInstantiation(_) and not exists(MacroInvocation mi | // cmp is in mi mi.getAnExpandedElement() = cmp and diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp new file mode 100644 index 00000000000..e50273aacde --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp @@ -0,0 +1,3 @@ +bool foo(int n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp new file mode 100644 index 00000000000..7f69e374ed1 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -0,0 +1,4 @@ +bool bar(unsigned short n1, unsigned short delta) { + // NB: Comparison is always false + return n1 + delta < n1; // GOOD (but misleading) +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp new file mode 100644 index 00000000000..424684ee2ec --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -0,0 +1,4 @@ +#include +bool foo(int n1, unsigned short delta) { + return n1 > INT_MAX - delta; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp new file mode 100644 index 00000000000..de8de2b9847 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp @@ -0,0 +1,3 @@ +bool bar(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n1; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp new file mode 100644 index 00000000000..621ae3273fd --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -0,0 +1,115 @@ + + + +

+When checking for integer overflow, you may often write tests like +a + b < a. This works fine if a or +b are unsigned integers, since any overflow in the addition +will cause the value to simply "wrap around." However, using +signed integers is problematic because signed 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. +

+
+ +

+Solutions to this problem can be thought of as falling into one of two +categories: (1) rewrite the signed expression so that overflow cannot occur +but the signedness remains, or (2) rewrite (or cast) the signed expression +into unsigned form. +

+ +

+Below we list examples of expressions where signed overflow may +occur, along with proposed solutions. The list should not be +considered exhaustive. +

+ +

+Given unsigned short i, delta and i + delta < i, +it is possible to rewrite it as (unsigned short)(i + delta) < i. +Note that i + deltadoes not actually overflow, due to int promotion +

+ +

+Given unsigned short i, delta and i + delta < i, +it is also possible to rewrite it as USHORT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included. +

+ +

+Given int i, delta and i + delta < i, +it is possible to rewrite it as INT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included. +

+ +

+Given int i, delta and i + delta < i, +it is also possible to rewrite it as (unsigned)i + delta < i. +Note that program semantics are affected by this change. +

+ +

+Given int i, delta and i + delta < i, +it is also possible to rewrite it as unsigned int i, delta and +i + delta < i. Note that program semantics are +affected by this change. +

+
+ + +

+In the following example, even though delta has been declared +unsigned short, C/C++ type promotion rules require that its +type is promoted to the larger type used in the addition and comparison, +namely a signed int. Addition is performed on +signed integers, and may have undefined behavior if an overflow occurs. +As a result, the entire (comparison) expression may also have an undefined +result. +

+ +

+The following example builds upon the previous one. Instead of +performing an addition (which could overflow), we have re-framed the +solution so that a subtraction is used instead. Since delta +is promoted to a signed int and INT_MAX denotes +the largest possible positive value for an signed int, +the expression INT_MAX - delta can never be less than zero +or more than INT_MAX. Hence, any overflow and underflow +are avoided. +

+ +

+In the following example, even though both n and delta +have been declared unsigned short, both are promoted to +signed int prior to addition. Because we started out with the +narrower short type, the addition is guaranteed not to overflow +and is therefore defined. But the fact that n1 + delta never +overflows means that the condition n1 + delta < n1 will never +hold true, which likely is not what the programmer intended. (see also the +cpp/bad-addition-overflow-check query). +

+ +

+The next example provides a solution to the previous one. Even though +i + delta does not overflow, casting it to an +unsigned short truncates the addition modulo 2^16, +so that unsigned short "wrap around" may now be observed. +Furthermore, since the left-hand side is now of type unsigned short, +the right-hand side does not need to be promoted to a signed int. +

+ + +
+ +
  • comp.lang.c FAQ list ยท Question 3.19 (Preserving rules)
  • +
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • +
  • W. Dietz, P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • +
    +
    diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql new file mode 100644 index 00000000000..648846a7dc1 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -0,0 +1,31 @@ +/** + * @name Undefined result of signed test for overflow + * @description Testing for overflow by adding a value to a variable + * to see if it "wraps around" works only for + * unsigned integer values. + * @kind problem + * @problem.severity warning + * @precision high + * @id cpp/signed-overflow-check + * @tags reliability + * security + */ + +import cpp +private import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2 +where + ro.getAnOperand() = add and + add.getAnOperand() = expr1 and + ro.getAnOperand() = expr2 and + globalValueNumber(expr1) = globalValueNumber(expr2) and + add.getUnspecifiedType().(IntegralType).isSigned() and + not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and + exprMightOverflowPositively(add) and + exists(Compilation c | c.getAFileCompiled() = ro.getFile() | + not c.getAnArgument() = "-fwrapv" and + not c.getAnArgument() = "-fno-strict-overflow" + ) +select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp index 522d6cde74c..fc8f309f73a 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp @@ -14,7 +14,7 @@ byte order function, such as ntohl. The use of a network-to-host byte order function is therefore a good indicator that the returned value is unvalidated data retrieved from the network, and should not be used without further validation. In particular, the returned value should not be used as an array index or array length -value without validation, which may result in a buffer overflow vulnerability. +value without validation, as this could result in a buffer overflow vulnerability.

    diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 83ed90bafab..53ad71cb22d 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -13,32 +13,33 @@ import semmle.code.cpp.security.boostorg.asio.protocols class ExistsAnyFlowConfig extends DataFlow::Configuration { ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } - override predicate isSource(DataFlow::Node source) { any() } + override predicate isSource(DataFlow::Node source) { + exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr()) + } - override predicate isSink(DataFlow::Node sink) { any() } + override predicate isSink(DataFlow::Node sink) { + exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions | + f.getACallToThisFunction() = fcSetOptions and + fcSetOptions.getQualifier() = sink.asExpr() + ) + } } bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, - Expr optionsSink - | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and - exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) + exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions | + anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | + contextSetOptions = fcSetOptions.getQualifier() and + forall( + Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, + Expr optionArgumentSource + | + optionArgument = fcSetOptions.getArgument(0) and + optionArgConfig + .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + | + optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag ) ) ) @@ -46,43 +47,18 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { bindingset[flag] predicate isOptionNotSet(ConstructorCall cc, int flag) { - not exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, - Expr optionsSink - | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and - exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f | - f.getACallToThisFunction() = fcSetOptions - | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) - ) - ) - ) + not exists(FunctionCall fcSetOptions | isOptionSet(cc, flag, fcSetOptions)) } from - BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, - BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink, - ConstructorCall cc, Expr e, string msg + BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource, + Expr protocolSink, ConstructorCall cc, Expr e, string msg where configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and ( BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and @@ -91,8 +67,7 @@ where or BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2()) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index fe6b455fa9b..963a726ae54 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -126,7 +126,7 @@ class SALParameter extends Parameter { } /** - * A SAL element, i.e. a SAL annotation or a declaration entry + * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. */ library class SALElement extends Element { diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp index ccd297c3b36..4ad7a40fed6 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp @@ -34,7 +34,7 @@ characters before writing to the HTML page.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp index b9118edc736..8e6a8903483 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp @@ -37,7 +37,7 @@ which is then subsequently accessed to fetch properties of the device. However, check the return value from the function call to initDeviceConfig. If the device number passed to the notify function was invalid, the initDeviceConfig function will leave the config variable uninitialized, -which would result in the notify function accessing uninitialized memory.

    +which will result in the notify function accessing uninitialized memory.

    diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql index eb00fb9ea10..f9eb2fe5400 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql @@ -2,7 +2,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 - * state, and reading the variable may result in undefined behaviour. + * state, and reading the variable may result in undefined behavior. * @kind problem * @problem.severity warning * @opaque-id SM02313 diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c index 1f281f3cfd9..73a01c2d900 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c @@ -19,7 +19,7 @@ int notify(int deviceNumber) { DeviceConfig config; initDeviceConfig(&config, deviceNumber); // BAD: Using config without checking the status code that is returned - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } -} \ No newline at end of file +} diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c index a9dcc06c9a5..ced43a66cfc 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c @@ -20,8 +20,8 @@ void notify(int deviceNumber) { int statusCode = initDeviceConfig(&config, deviceNumber); if (statusCode == 0) { // GOOD: Status code returned by initialization function is checked, so this is safe - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } } -} \ No newline at end of file +} diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 240bd7aa25e..bac7874da4d 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -89,9 +89,9 @@ class ParameterNullCheck extends ParameterCheck { ( va = this.(NotExpr).getOperand() or va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or - va = getAssertedFalseCondition(this) or + va = getCheckedFalseCondition(this) or va = any(NEExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) or @@ -101,7 +101,7 @@ class ParameterNullCheck extends ParameterCheck { va = this or va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or va = any(EQExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) ) @@ -567,7 +567,7 @@ Expr getAnInitializedArgument(Call call) { result = call.getArgument(initialized * the call, under the given context and evidence. */ pragma[nomagic] -int conditionallyInitializedArgument( +private int conditionallyInitializedArgument( Call call, ConditionalInitializationFunction target, Context c, Evidence e ) { target = getTarget(call) and @@ -588,7 +588,7 @@ Expr getAConditionallyInitializedArgument( /** * Gets the type signature for the functions parameters. */ -string typeSig(Function f) { +private string typeSig(Function f) { result = concat(int i, Type pt | pt = f.getParameter(i).getType() | @@ -599,7 +599,7 @@ string typeSig(Function f) { /** * Holds where qualifiedName and typeSig make up the signature for the function. */ -predicate functionSignature(Function f, string qualifiedName, string typeSig) { +private predicate functionSignature(Function f, string qualifiedName, string typeSig) { qualifiedName = f.getQualifiedName() and typeSig = typeSig(f) } @@ -611,7 +611,7 @@ predicate functionSignature(Function f, string qualifiedName, string typeSig) { * This is useful for identifying call to target dependencies across libraries, where the libraries * are never statically linked together. */ -Function getAPossibleDefinition(Function undefinedFunction) { +private Function getAPossibleDefinition(Function undefinedFunction) { not undefinedFunction.isDefined() and exists(string qn, string typeSig | functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig) @@ -620,32 +620,47 @@ Function getAPossibleDefinition(Function undefinedFunction) { } /** - * Gets a possible target for the Call, using the name and parameter matching if we did not associate + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If there is at least one defined target after performing some simple virtual dispatch + * resolution, then the result is all the defined targets. + */ +private Function getTarget1(Call c) { + result = VirtualDispatch::getAViableTarget(c) and + result.isDefined() +} + +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If we can use the heuristic matching of functions to find definitions for some of the viable + * targets, return those. + */ +private Function getTarget2(Call c) { + not exists(getTarget1(c)) and + result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) +} + +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * Otherwise, the result is the undefined `Function` instances. + */ +private Function getTarget3(Call c) { + not exists(getTarget1(c)) and + not exists(getTarget2(c)) and + result = VirtualDispatch::getAViableTarget(c) +} + +/** + * Gets a possible target for the `Call`, using the name and parameter matching if we did not associate * this call with a specific definition at link or compile time, and performing simple virtual * dispatch resolution. */ Function getTarget(Call c) { - if VirtualDispatch::getAViableTarget(c).isDefined() - then - /* - * If there is at least one defined target after performing some simple virtual dispatch - * resolution, then the result is all the defined targets. - */ - - result = VirtualDispatch::getAViableTarget(c) and - result.isDefined() - else - if exists(getAPossibleDefinition(VirtualDispatch::getAViableTarget(c))) - then - /* - * If we can use the heuristic matching of functions to find definitions for some of the viable - * targets, return those. - */ - - result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) - else - // Otherwise, the result is the undefined `Function` instances - result = VirtualDispatch::getAViableTarget(c) + result = getTarget1(c) or + result = getTarget2(c) or + result = getTarget3(c) } /** @@ -669,7 +684,7 @@ FieldAccess getAFieldAccess(Variable v) { } /** - * Gets a condition which is asserted to be false by the given `ne` expression, according to this pattern: + * Gets a condition which is checked to be false by the given `ne` expression, according to this pattern: * ``` * int a = !!result; * if (!a) { // <- ne @@ -677,7 +692,7 @@ FieldAccess getAFieldAccess(Variable v) { * } * ``` */ -Expr getAssertedFalseCondition(NotExpr ne) { +private Expr getCheckedFalseCondition(NotExpr ne) { exists(LocalVariable v | result = v.getInitializer().getExpr().(NotExpr).getOperand().(NotExpr).getOperand() and ne.getOperand() = v.getAnAccess() and diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5ac4f52392e..297654a1afa 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -605,15 +605,6 @@ class Class extends UserType { class_instantiation(underlyingElement(this), unresolveElement(c)) } - /** - * Gets the `i`th template argument used to instantiate this class from a - * class template. When called on a class template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgument(int i) { - class_template_argument(underlyingElement(this), i, unresolveElement(result)) - } - /** * Holds if this class/struct is polymorphic (has a virtual function, or * inherits one). @@ -623,7 +614,7 @@ class Class extends UserType { } override predicate involvesTemplateParameter() { - getATemplateArgument().involvesTemplateParameter() + getATemplateArgument().(Type).involvesTemplateParameter() } /** Holds if this class, struct or union was declared 'final'. */ diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 5d13bf4883a..04135880129 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -193,20 +193,83 @@ abstract class Declaration extends Locatable, @declaration { /** * Gets a template argument used to instantiate this declaration from a template. - * When called on a template, this will return a template parameter. + * When called on a template, this will return a template parameter type for + * both typed and non-typed parameters. */ - final Type getATemplateArgument() { result = getTemplateArgument(_) } + final Locatable getATemplateArgument() { result = getTemplateArgument(_) } + + /** + * Gets a template argument used to instantiate this declaration from a template. + * When called on a template, this will return a non-typed template + * parameter value. + */ + final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a - * template. When called on a template, this will return the `i`th template parameter. + * template. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgument(0)` return `T`, and + * `getTemplateArgument(1)` return `X`. + * + * `Foo bar; + * + * Will have `getTemplateArgument())` return `int`, and + * `getTemplateArgument(1)` return `1`. */ - Type getTemplateArgument(int index) { none() } + final Locatable getTemplateArgument(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentValue(index) + else result = getTemplateArgumentType(index) + } + + /** + * Gets the `i`th template argument value used to instantiate this declaration + * from a template. When called on a template, this will return the `i`th template + * parameter value if it exists. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgumentKind(1)` return `T`, and no result for + * `getTemplateArgumentKind(0)`. + * + * `Foo bar; + * + * Will have `getTemplateArgumentKind(1)` return `int`, and no result for + * `getTemplateArgumentKind(0)`. + */ + final Locatable getTemplateArgumentKind(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentType(index) + else none() + } /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + + private Type getTemplateArgumentType(int index) { + class_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument(underlyingElement(this), index, unresolveElement(result)) + } + + private Expr getTemplateArgumentValue(int index) { + class_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 94d11d63575..14edf014b21 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -343,15 +343,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { function_instantiation(underlyingElement(this), unresolveElement(f)) } - /** - * Gets the `i`th template argument used to instantiate this function from a - * function template. When called on a function template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgument(int index) { - function_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that diff --git a/cpp/ql/src/semmle/code/cpp/NestedFields.qll b/cpp/ql/src/semmle/code/cpp/NestedFields.qll index 12109be8ece..c4be8b8b9ff 100644 --- a/cpp/ql/src/semmle/code/cpp/NestedFields.qll +++ b/cpp/ql/src/semmle/code/cpp/NestedFields.qll @@ -1,9 +1,8 @@ import cpp /** - * Gets a `Field` that is nested within the given `Struct`. - * - * This identifies `Field`s which are located in the same memory + * Gets a `Field` that is within the given `Struct`, either directly or nested + * inside one or more levels of member structs. */ private Field getANestedField(Struct s) { result = s.getAField() @@ -15,7 +14,7 @@ private Field getANestedField(Struct s) { } /** - * Unwraps a series of field accesses to determine the inner-most qualifier. + * Unwraps a series of field accesses to determine the outer-most qualifier. */ private Expr getUltimateQualifier(FieldAccess fa) { exists(Expr qualifier | qualifier = fa.getQualifier() | diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index ab979d89b03..e3ad19f6028 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -35,6 +35,14 @@ private string getParameterTypeString(Type parameterType) { else result = parameterType.(DumpType).getTypeIdentityString() } +private string getTemplateArgumentString(Declaration d, int i) { + if exists(d.getTemplateArgumentKind(i)) + then + result = d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " + + d.getTemplateArgument(i) + else result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() +} + /** * A `Declaration` extended to add methods for generating strings useful only for dumps and debugging. */ @@ -56,7 +64,7 @@ abstract private class DumpDeclaration extends Declaration { strictconcat(int i | exists(this.getTemplateArgument(i)) | - this.getTemplateArgument(i).(DumpType).getTypeIdentityString(), ", " order by i + getTemplateArgumentString(this, i), ", " order by i ) + ">" else result = "" } diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 10a1b6b1724..ea1e7fd5026 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -210,7 +210,7 @@ class Type extends Locatable, @type { // A function call that provides an explicit template argument that refers to T uses T. // We exclude calls within instantiations, since they do not appear directly in the source. exists(FunctionCall c | - c.getAnExplicitTemplateArgument().refersTo(this) and + c.getAnExplicitTemplateArgument().(Type).refersTo(this) and result = c and not c.getEnclosingFunction().isConstructedFrom(_) ) diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 6fd33d9a037..194cc5333c7 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -155,15 +155,6 @@ class Variable extends Declaration, @variable { variable_instantiation(underlyingElement(this), unresolveElement(v)) } - /** - * Gets the `i`th template argument used to instantiate this variable from a - * variable template. When called on a variable template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgument(int index) { - variable_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this is a compiler-generated variable. For example, a * [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll index bd179fe27cc..5bb60564c1b 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Printf.qll @@ -8,25 +8,32 @@ import semmle.code.cpp.commons.StringAnalysis import semmle.code.cpp.models.interfaces.FormattingFunction import semmle.code.cpp.models.implementations.Printf +class PrintfFormatAttribute extends FormatAttribute { + PrintfFormatAttribute() { + getArchetype() = "printf" or + getArchetype() = "__printf__" + } +} + /** * A function that can be identified as a `printf` style formatting * function by its use of the GNU `format` attribute. */ class AttributeFormattingFunction extends FormattingFunction { - FormatAttribute printf_attrib; - override string getCanonicalQLClass() { result = "AttributeFormattingFunction" } AttributeFormattingFunction() { - printf_attrib = getAnAttribute() and - ( - printf_attrib.getArchetype() = "printf" or - printf_attrib.getArchetype() = "__printf__" - ) and - exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions + exists(PrintfFormatAttribute printf_attrib | + printf_attrib = getAnAttribute() and + exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions + ) } - override int getFormatParameterIndex() { result = printf_attrib.getFormatIndex() } + override int getFormatParameterIndex() { + forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() | + result = printf_attrib.getFormatIndex() + ) + } } /** @@ -124,15 +131,17 @@ class FormattingFunctionCall extends Expr { } /** - * Gets the argument corresponding to the nth conversion specifier + * Gets the argument corresponding to the nth conversion specifier. */ Expr getConversionArgument(int n) { - exists(FormatLiteral fl, int b, int o | + exists(FormatLiteral fl | fl = this.getFormat() and - b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and - o = fl.getNumArgNeeded(n) and - o > 0 and - result = this.getFormatArgument(b + o - 1) + ( + result = this.getFormatArgument(fl.getParameterFieldValue(n)) + or + result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 2)) and + not exists(fl.getParameterFieldValue(n)) + ) ) } @@ -142,11 +151,14 @@ class FormattingFunctionCall extends Expr { * an explicit minimum field width). */ Expr getMinFieldWidthArgument(int n) { - exists(FormatLiteral fl, int b | + exists(FormatLiteral fl | fl = this.getFormat() and - b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and - fl.hasImplicitMinFieldWidth(n) and - result = this.getFormatArgument(b) + ( + result = this.getFormatArgument(fl.getMinFieldWidthParameterFieldValue(n)) + or + result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 0)) and + not exists(fl.getMinFieldWidthParameterFieldValue(n)) + ) ) } @@ -156,12 +168,14 @@ class FormattingFunctionCall extends Expr { * precision). */ Expr getPrecisionArgument(int n) { - exists(FormatLiteral fl, int b, int o | + exists(FormatLiteral fl | fl = this.getFormat() and - b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and - (if fl.hasImplicitMinFieldWidth(n) then o = 1 else o = 0) and - fl.hasImplicitPrecision(n) and - result = this.getFormatArgument(b + o) + ( + result = this.getFormatArgument(fl.getPrecisionParameterFieldValue(n)) + or + result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 1)) and + not exists(fl.getPrecisionParameterFieldValue(n)) + ) ) } @@ -361,6 +375,14 @@ class FormatLiteral extends Literal { */ string getParameterField(int n) { this.parseConvSpec(n, _, result, _, _, _, _, _) } + /** + * Gets the parameter field of the nth conversion specifier (if it has one) as a + * zero-based number. + */ + int getParameterFieldValue(int n) { + result = this.getParameterField(n).regexpCapture("([0-9]*)\\$", 1).toInt() - 1 + } + /** * Gets the flags of the nth conversion specifier. */ @@ -430,6 +452,14 @@ class FormatLiteral extends Literal { */ int getMinFieldWidth(int n) { result = this.getMinFieldWidthOpt(n).toInt() } + /** + * Gets the zero-based parameter number of the minimum field width of the nth + * conversion specifier, if it is implicit and uses a parameter field (such as `*1$`). + */ + int getMinFieldWidthParameterFieldValue(int n) { + result = this.getMinFieldWidthOpt(n).regexpCapture("\\*([0-9]*)\\$", 1).toInt() - 1 + } + /** * Gets the precision of the nth conversion specifier (empty string if none is given). */ @@ -460,6 +490,14 @@ class FormatLiteral extends Literal { else result = this.getPrecisionOpt(n).regexpCapture("\\.([0-9]*)", 1).toInt() } + /** + * Gets the zero-based parameter number of the precision of the nth conversion + * specifier, if it is implicit and uses a parameter field (such as `*1$`). + */ + int getPrecisionParameterFieldValue(int n) { + result = this.getPrecisionOpt(n).regexpCapture("\\.\\*([0-9]*)\\$", 1).toInt() - 1 + } + /** * Gets the length flag of the nth conversion specifier. */ @@ -777,19 +815,49 @@ class FormatLiteral extends Literal { ) } + /** + * Holds if the nth conversion specifier of this format string (if `mode = 2`), it's + * minimum field width (if `mode = 0`) or it's precision (if `mode = 1`) requires a + * format argument. + * + * Most conversion specifiers require a format argument, whereas minimum field width + * and precision only require a format argument if they are present and a `*` was + * used for it's value in the format string. + */ + private predicate hasFormatArgumentIndexFor(int n, int mode) { + mode = 0 and + this.hasImplicitMinFieldWidth(n) + or + mode = 1 and + this.hasImplicitPrecision(n) + or + mode = 2 and + exists(this.getConvSpecOffset(n)) and + not this.getConversionChar(n) = "m" + } + + /** + * Gets the computed format argument index for the nth conversion specifier of this + * format string (if `mode = 2`), it's minimum field width (if `mode = 0`) or it's + * precision (if `mode = 1`). Has no result if that element is not present. Does + * not account for positional arguments (`$`). + */ + int getFormatArgumentIndexFor(int n, int mode) { + hasFormatArgumentIndexFor(n, mode) and + (3 * n) + mode = rank[result + 1](int n2, int mode2 | + hasFormatArgumentIndexFor(n2, mode2) + | + (3 * n2) + mode2 + ) + } + /** * Gets the number of arguments required by the nth conversion specifier * of this format string. */ int getNumArgNeeded(int n) { exists(this.getConvSpecOffset(n)) and - not this.getConversionChar(n) = "%" and - exists(int n1, int n2, int n3 | - (if this.hasImplicitMinFieldWidth(n) then n1 = 1 else n1 = 0) and - (if this.hasImplicitPrecision(n) then n2 = 1 else n2 = 0) and - (if this.getConversionChar(n) = "m" then n3 = 0 else n3 = 1) and - result = n1 + n2 + n3 - ) + result = count(int mode | hasFormatArgumentIndexFor(n, mode)) } /** @@ -801,7 +869,7 @@ class FormatLiteral extends Literal { // At least one conversion specifier has a parameter field, in which case, // they all should have. result = max(string s | this.getParameterField(_) = s + "$" | s.toInt()) - else result = sum(int n, int toSum | toSum = this.getNumArgNeeded(n) | toSum) + else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode)) } /** diff --git a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll index 2fa9322843e..9992f88867b 100644 --- a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll @@ -28,6 +28,19 @@ module VirtualDispatch { not result.hasName("IUnknown") } + /** + * Helper predicate for `getAViableTarget`, which computes the viable targets for + * virtual calls based on the qualifier type. + */ + private Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) { + exists(Class qualifierSubType | + result = getAPossibleImplementation(staticTarget) and + qualifierType = qualifierSubType.getABaseClass*() and + mayInherit(qualifierSubType, result) and + not cannotInherit(qualifierSubType, result) + ) + } + /** * Gets a viable target for the given function call. * @@ -42,18 +55,9 @@ module VirtualDispatch { * If `c` is not a virtual call, the result will be `c.getTarget()`. */ Function getAViableTarget(Call c) { - exists(Function staticTarget | staticTarget = c.getTarget() | - if c.(FunctionCall).isVirtual() and staticTarget instanceof MemberFunction - then - exists(Class qualifierType, Class qualifierSubType | - result = getAPossibleImplementation(staticTarget) and - qualifierType = getCallQualifierType(c) and - qualifierType = qualifierSubType.getABaseClass*() and - mayInherit(qualifierSubType, result) and - not cannotInherit(qualifierSubType, result) - ) - else result = staticTarget - ) + if c.(FunctionCall).isVirtual() and c.getTarget() instanceof MemberFunction + then result = getAViableVirtualCallTarget(getCallQualifierType(c), c.getTarget()) + else result = c.getTarget() } /** Holds if `f` is declared in `c` or a transitive base class of `c`. */ @@ -63,7 +67,7 @@ module VirtualDispatch { /** * Holds if `c` cannot inherit the member function `f`, - * i.e. `c` or one of its supertypes overrides `f`. + * that is, `c` or one of its supertypes overrides `f`. */ private predicate cannotInherit(Class c, MemberFunction f) { exists(Class overridingType, MemberFunction override | diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 882918316f6..22a25969a8f 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -139,17 +139,29 @@ class FunctionCall extends Call, @funbindexpr { override string getCanonicalQLClass() { result = "FunctionCall" } /** Gets an explicit template argument for this call. */ - Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + + /** Gets an explicit template argument value for this call. */ + Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) } /** Gets a template argument for this call. */ - Type getATemplateArgument() { result = getTarget().getATemplateArgument() } + Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() } + + /** Gets a template argument value for this call. */ + Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() } /** Gets the nth explicit template argument for this call. */ - Type getExplicitTemplateArgument(int n) { + Locatable getExplicitTemplateArgument(int n) { n < getNumberOfExplicitTemplateArguments() and result = getTemplateArgument(n) } + /** Gets the nth explicit template argument value for this call. */ + Locatable getExplicitTemplateArgumentKind(int n) { + n < getNumberOfExplicitTemplateArguments() and + result = getTemplateArgumentKind(n) + } + /** Gets the number of explicit template arguments for this call. */ int getNumberOfExplicitTemplateArguments() { if numtemplatearguments(underlyingElement(this), _) @@ -161,7 +173,10 @@ class FunctionCall extends Call, @funbindexpr { int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } /** Gets the nth template argument for this call (indexed from 0). */ - Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + + /** Gets the nth template argument value for this call (indexed from 0). */ + Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) } /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 0753dfd266e..e0135e0ad2f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.security.Security private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch /** * A predictable instruction is one where an external user can predict @@ -145,7 +146,8 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { } Function resolveCall(Call call) { - // TODO: improve virtual dispatch. This will help in the test for - // `UncontrolledProcessOperation.ql`. - result = call.getTarget() + exists(CallInstruction callInstruction | + callInstruction.getAST() = call and + result = Dispatch::viableCallable(callInstruction) + ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index d0325a28d3e..9572639de59 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -1,5 +1,6 @@ private import cpp private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.DataFlow Function viableImpl(CallInstruction call) { result = viableCallable(call) } @@ -20,6 +21,58 @@ Function viableCallable(CallInstruction call) { functionSignatureWithBody(qualifiedName, nparams, result) and strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 ) + or + // Rudimentary virtual dispatch support. It's essentially local data flow + // where the source is a derived-to-base conversion and the target is the + // qualifier of a call. + exists(Class derived, DataFlow::Node thisArgument | + nodeMayHaveClass(derived, thisArgument) and + overrideMayAffectCall(derived, thisArgument, _, result, call) + ) +} + +/** + * Holds if `call` is a virtual function call with qualifier `thisArgument` in + * `enclosingFunction`, whose static target is overridden by + * `overridingFunction` in `overridingClass`. + */ +pragma[noinline] +private predicate overrideMayAffectCall( + Class overridingClass, DataFlow::Node thisArgument, Function enclosingFunction, + MemberFunction overridingFunction, CallInstruction call +) { + call.getEnclosingFunction() = enclosingFunction and + overridingFunction.getAnOverriddenFunction+() = call.getStaticCallTarget() and + overridingFunction.getDeclaringType() = overridingClass and + thisArgument = DataFlow::instructionNode(call.getThisArgument()) +} + +/** + * Holds if `node` may have dynamic class `derived`, where `derived` is a class + * that may affect virtual dispatch within the enclosing function. + * + * For the sake of performance, this recursion is written out manually to make + * it a relation on `Class x Node` rather than `Node x Node` or `MemberFunction + * x Node`, both of which would be larger. It's a forward search since there + * should usually be fewer classes than calls. + * + * If a value is cast several classes up in the hierarchy, that will be modeled + * as a chain of `ConvertToBaseInstruction`s and will cause the search to start + * from each of them and pass through subsequent ones. There might be + * performance to gain by stopping before a second upcast and reconstructing + * the full chain in a "big-step" recursion after this one. + */ +private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) { + exists(ConvertToBaseInstruction toBase | + derived = toBase.getDerivedClass() and + overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and + node.asInstruction() = toBase + ) + or + exists(DataFlow::Node prev | + nodeMayHaveClass(derived, prev) and + DataFlow::localFlowStep(prev, node) + ) } /** diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index f824e0b6bf2..4e84424fcb7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -205,7 +205,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo.(CopyInstruction).getSourceValue() = iFrom or iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or // Treat all conversions as flow, even conversions between different numeric types. - iTo.(ConvertInstruction).getUnary() = iFrom + iTo.(ConvertInstruction).getUnary() = iFrom or + iTo.(InheritanceConversionInstruction).getUnary() = iFrom } /** @@ -214,6 +215,14 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction */ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } +/** + * Holds if data can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionFlow(Instruction e1, Instruction e2) { + localFlow(instructionNode(e1), instructionNode(e2)) +} + /** * Holds if data can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index e34709e94ec..8d7c9194f4f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -53,6 +53,14 @@ private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction no */ predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } +/** + * Holds if taint can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionTaint(Instruction i1, Instruction i2) { + localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2)) +} + /** * Holds if taint can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 0abfa14023d..73cdbd20989 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or @@ -42,6 +43,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +109,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +120,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +147,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +162,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +176,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +193,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +208,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +239,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index eb07be7f30c..0e4f800bb1b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -34,7 +34,7 @@ private newtype TOpcode = TPointerSub() or TPointerDiff() or TConvert() or - TConvertToBase() or + TConvertToNonVirtualBase() or TConvertToVirtualBase() or TConvertToDerived() or TCheckedConvertOrNull() or @@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { } abstract class CopyOpcode extends Opcode { } +abstract class ConvertToBaseOpcode extends UnaryOpcode { } + abstract class MemoryAccessOpcode extends Opcode { } abstract class ReturnOpcode extends Opcode { } @@ -302,11 +304,11 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToBase extends UnaryOpcode, TConvertToBase { - final override string toString() { result = "ConvertToBase" } + class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase { + final override string toString() { result = "ConvertToNonVirtualBase" } } - class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { + class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase { final override string toString() { result = "ConvertToVirtualBase" } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 049983c9126..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { @@ -983,14 +981,22 @@ class InheritanceConversionInstruction extends UnaryInstruction { * to the address of a direct non-virtual base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..6ecfd1470bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { instr = operand.getUse() and ( // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | + exists(ConvertToNonVirtualBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) ) @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index 955d422cf9a..0835ffb7da6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -210,17 +210,21 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) { def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap or - // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable. + // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable, + // unless the location is read-only. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownMemoryLocation and - result instanceof MayPartiallyOverlap + result instanceof MayPartiallyOverlap and + not use.(VariableMemoryLocation).getVariable().isReadOnly() or // An UnknownNonLocalMemoryLocation may partially overlap any location within the same virtual - // variable, except a local variable. + // variable, except a local variable or read-only variable. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownNonLocalMemoryLocation and result instanceof MayPartiallyOverlap and - not use.(VariableMemoryLocation).getVariable() instanceof IRAutomaticVariable + not exists(IRVariable var | var = use.(VariableMemoryLocation).getVariable() | + var instanceof IRAutomaticVariable or var.isReadOnly() + ) or exists(VariableMemoryLocation defVariableLocation | defVariableLocation = def and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd..01c135abf13 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 049983c9126..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { @@ -983,14 +981,22 @@ class InheritanceConversionInstruction extends UnaryInstruction { * to the address of a direct non-virtual base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index fbf6b7e3d08..628aae26995 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -44,6 +44,13 @@ private module Cached { ) } + cached + predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) { + literal = ast and + literal.getEnclosingFunction() = func and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -51,20 +58,23 @@ private module Cached { Expr getInstructionConvertedResultExpression(Instruction instruction) { exists(TranslatedExpr translatedExpr | translatedExpr = getTranslatedExpr(result) and - instruction = translatedExpr.getResult() + instruction = translatedExpr.getResult() and + // Only associate `instruction` with this expression if the translated + // expression actually produced the instruction; not if it merely + // forwarded the result of another translated expression. + instruction = translatedExpr.getInstruction(_) ) } cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) { - exists(Expr converted, TranslatedExpr translatedExpr | + exists(Expr converted | result = converted.(Conversion).getExpr+() or result = converted | not result instanceof Conversion and - translatedExpr = getTranslatedExpr(converted) and - instruction = translatedExpr.getResult() + converted = getInstructionConvertedResultExpression(instruction) ) } @@ -231,8 +241,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -263,12 +279,6 @@ private module Cached { ) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index edb26b1c8be..7b0d33546cf 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -45,6 +45,7 @@ newtype TInstructionTag = ConditionValueResultLoadTag() or BoolConversionConstantTag() or BoolConversionCompareTag() or + ResultCopyTag() or LoadTag() or // Implicit load due to lvalue-to-rvalue conversion CatchTag() or ThrowTag() or diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 294a539ec31..15b5db3ef74 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -120,7 +120,8 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or - getInitialization() instanceof TranslatedListInitialization + getInitialization() instanceof TranslatedListInitialization or + getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index aefdeff9e51..2bffcdcc8ae 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -9,6 +9,7 @@ private import InstructionTag private import TranslatedCondition private import TranslatedFunction private import TranslatedStmt +private import TranslatedExpr private import IRConstruction private import semmle.code.cpp.models.interfaces.SideEffect @@ -235,6 +236,15 @@ newtype TTranslatedElement = expr.hasLValueToRValueConversion() and not ignoreLoad(expr) } or + TTranslatedResultCopy(Expr expr) { + not ignoreExpr(expr) and + exprNeedsCopyIfNotLoaded(expr) and + // Doesn't have a TTranslatedLoad + not ( + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) + ) + } or // An expression most naturally translated as control flow. TTranslatedNativeCondition(Expr expr) { not ignoreExpr(expr) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 3fc73d66878..9db42c742ac 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -62,12 +62,11 @@ abstract class TranslatedExpr extends TranslatedElement { /** * Holds if the result of this `TranslatedExpr` is a glvalue. */ - private predicate isResultGLValue() { + predicate isResultGLValue() { + // This implementation is overridden in `TranslatedCoreExpr` to mark them + // as glvalues if they have loads on them. It's not overridden in + // `TranslatedResultCopy` since result copies never have loads. expr.isGLValueCategory() - or - // If this TranslatedExpr doesn't produce the result, then it must represent - // a glvalue that is then loaded by a TranslatedLoad. - not producesExprResult() } final override Locatable getAST() { result = expr } @@ -96,14 +95,28 @@ abstract class TranslatedExpr extends TranslatedElement { abstract class TranslatedCoreExpr extends TranslatedExpr { final override string toString() { result = expr.toString() } + /** + * Holds if the result of this `TranslatedExpr` is a glvalue. + */ + override predicate isResultGLValue() { + super.isResultGLValue() + or + // If this TranslatedExpr doesn't produce the result, then it must represent + // a glvalue that is then loaded by a TranslatedLoad. + hasLoad() + } + + final predicate hasLoad() { + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) + } + final override predicate producesExprResult() { // If there's no load, then this is the only TranslatedExpr for this // expression. - not expr.hasLValueToRValueConversion() - or - // If we're supposed to ignore the load on this expression, then this - // is the only TranslatedExpr. - ignoreLoad(expr) + not hasLoad() and + // If there's a result copy, then this expression's result is the copy. + not exprNeedsCopyIfNotLoaded(expr) } } @@ -288,6 +301,48 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { private TranslatedCoreExpr getOperand() { result.getExpr() = expr } } +/** + * IR translation of an implicit lvalue-to-rvalue conversion on the result of + * an expression. + */ +class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { + TranslatedResultCopy() { this = TTranslatedResultCopy(expr) } + + override string toString() { result = "Result of " + expr.toString() } + + override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + + override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = ResultCopyTag() and + opcode instanceof Opcode::CopyValue and + resultType = getOperand().getResultType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = ResultCopyTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getOperand() and result = getInstruction(ResultCopyTag()) + } + + override Instruction getResult() { result = getInstruction(ResultCopyTag()) } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = ResultCopyTag() and + operandTag instanceof UnaryOperandTag and + result = getOperand().getResult() + } + + final override predicate producesExprResult() { any() } + + private TranslatedCoreExpr getOperand() { result.getExpr() = expr } +} + class TranslatedCommaExpr extends TranslatedNonConstantExpr { override CommaExpr expr; @@ -983,7 +1038,7 @@ class TranslatedInheritanceConversion extends TranslatedSingleInstructionConvers then if expr.(BaseClassConversion).isVirtual() then result instanceof Opcode::ConvertToVirtualBase - else result instanceof Opcode::ConvertToBase + else result instanceof Opcode::ConvertToNonVirtualBase else result instanceof Opcode::ConvertToDerived } } @@ -2403,6 +2458,58 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { final override Opcode getOpcode() { result instanceof Opcode::Error } } +/** + * Holds if the translation of `expr` will not directly generate any + * `Instruction` for use as result. For such instructions we can synthesize a + * `CopyValue` instruction to ensure that there is a 1-to-1 mapping between + * expressions and result-bearing instructions. + */ +// This should ideally be a dispatch predicate on TranslatedNonConstantExpr, +// but it doesn't look monotonic to QL. +predicate exprNeedsCopyIfNotLoaded(Expr expr) { + ( + expr instanceof AssignExpr + or + expr instanceof AssignOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PrefixCrementOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PointerDereferenceExpr + or + expr instanceof AddressOfExpr + or + expr instanceof BuiltInOperationBuiltInAddressOf + or + // No case for ParenthesisExpr to avoid getting too many instructions + expr instanceof ReferenceDereferenceExpr + or + expr instanceof ReferenceToExpr + or + expr instanceof CommaExpr + or + expr instanceof ConditionDeclExpr + // TODO: simplify TranslatedStmtExpr too + ) and + not exprImmediatelyDiscarded(expr) +} + +/** + * Holds if `expr` is immediately discarded. Such expressions do not need a + * `CopyValue` because it's unlikely that anyone is interested in their value. + */ +private predicate exprImmediatelyDiscarded(Expr expr) { + exists(ExprStmt s | + s = expr.getParent() and + not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt()) + ) + or + exists(CommaExpr c | c.getLeftOperand() = expr) + or + exists(ForStmt for | for.getUpdate() = expr) +} + /** * The IR translation of an `__assume` expression. We currently translate these as `NoOp`. In the * future, we will probably want to do something better. At a minimum, we can model `__assume(0)` as diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 21ad11513bd..609f8276640 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -340,7 +340,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati * Holds if the `elementCount` array elements starting at `startIndex` must be * zero initialized. */ - private predicate zeroInitRange(int startIndex, int elementCount) { + predicate zeroInitRange(int startIndex, int elementCount) { exists(int targetCount | startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and @@ -752,7 +752,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = OnlyInstructionTag() and - opcode instanceof Opcode::ConvertToBase and + opcode instanceof Opcode::ConvertToNonVirtualBase and resultType = getTypeForGLValue(call.getTarget().getDeclaringType()) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126..6cc1127c4bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { @@ -983,14 +981,22 @@ class InheritanceConversionInstruction extends UnaryInstruction { * to the address of a direct non-virtual base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..6ecfd1470bb 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -109,7 +109,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { instr = operand.getUse() and ( // Converting to a non-virtual base class adds the offset of the base class. - exists(ConvertToBaseInstruction convert | + exists(ConvertToNonVirtualBaseInstruction convert | convert = instr and bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) ) @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 88184d90345..e967dc9920c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -175,6 +175,7 @@ private IRType getIRTypeForPRValue(Type type) { ) } +cached private newtype TCppType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TFunctionGLValueType() or @@ -203,6 +204,7 @@ class CppType extends TCppType { * Gets the `IRType` that represents this `CppType`. Many different `CppType`s can map to a single * `IRType`. */ + cached IRType getIRType() { none() } /** diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll index ae3733473ad..e113d5e5745 100644 --- a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -3,7 +3,7 @@ import semmle.code.cpp.dataflow.DataFlow module BoostorgAsio { /** - * Represents boost::asio::ssl::context enum + * Represents the `boost::asio::ssl::context` enum. */ class SslContextMethod extends Enum { SslContextMethod() { @@ -12,7 +12,7 @@ module BoostorgAsio { } /** - * returns the value for a banned protocol + * Gets an enumeration constant for a banned protocol. */ EnumConstant getABannedProtocolConstant() { result = this.getAnEnumConstant() and @@ -56,14 +56,15 @@ module BoostorgAsio { } /** - * returns the value for a approved protocols, but that are hard-coded (i.e. no protocol negotiation) + * Gets an enumeration constant for an approved protocol, that is hard-coded + * (no protocol negotiation). */ EnumConstant getAnApprovedButHardcodedProtocolConstant() { result = this.getATls12ProtocolConstant() } /** - * returns the value for a TLS v1.2 protocol + * Gets an enumeration constant for a TLS v1.2 protocol. */ EnumConstant getATls12ProtocolConstant() { result = this.getAnEnumConstant() and @@ -80,7 +81,7 @@ module BoostorgAsio { } /** - * returns the value for a TLS v1.3 protocol + * Gets an enumeration constant for a TLS v1.3 protocol. */ EnumConstant getATls13ProtocolConstant() { result = this.getAnEnumConstant() and @@ -97,7 +98,7 @@ module BoostorgAsio { } /** - * returns the value of a generic TLS or SSL/TLS protocol + * Gets an enumeration constant for a generic TLS or SSL/TLS protocol. */ EnumConstant getAGenericTlsProtocolConstant() { result = this.getAnEnumConstant() and @@ -116,7 +117,7 @@ module BoostorgAsio { } /** - * returns the value of a generic SSL/TLS protocol + * Gets an enumeration constant for a generic SSL/TLS protocol. */ EnumConstant getASslv23ProtocolConstant() { result = this.getAnEnumConstant() and @@ -135,7 +136,9 @@ module BoostorgAsio { } /** - * NOTE: ignore - Modern versions of OpenSSL do not support SSL v2 anymore, so this option is for backwards compatibility only + * Gets the value for the no_sslv2 constant, right shifted by 16 bits. + * + * Note that modern versions of OpelSSL do not support SSL v2, so this option is for backwards compatibility only. */ int getShiftedSslOptionsNoSsl2() { // SSL_OP_NO_SSLv2 was removed from modern OpenSSL versions @@ -143,7 +146,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_sslv3 constant + * Gets the value for the no_sslv3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoSsl3() { // SSL_OP_NO_SSLv3 == 0x02000000U @@ -151,7 +154,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1 constant + * Gets the value for the no_tlsv1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1() { // SSL_OP_NO_TLSv1 == 0x04000000U @@ -159,7 +162,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_1 constant + * Gets the value for the no_tlsv1_1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_1() { // SSL_OP_NO_TLSv1_1 == 0x10000000U @@ -167,7 +170,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_2 constant + * Gets the value for the no_tlsv1_2 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_2() { // SSL_OP_NO_TLSv1_2 == 0x08000000U @@ -175,7 +178,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_3 constant + * Gets the value for the no_tlsv1_3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_3() { // SSL_OP_NO_TLSv1_2 == 0x20000000U @@ -183,7 +186,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context class + * Represents the `boost::asio::ssl::context` class. */ class SslContextClass extends Class { SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" } @@ -196,7 +199,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context::set_options member function + * Represents `boost::asio::ssl::context::set_options` member function. */ class SslSetOptionsFunction extends Function { SslSetOptionsFunction() { @@ -205,7 +208,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a banned protocol + * Holds if the expression represents a banned protocol. */ predicate isExprBannedBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -244,7 +247,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a TLS v1.2 protocol + * Holds if the expression represents a TLS v1.2 protocol. */ predicate isExprTls12BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -269,7 +272,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a protocol that requires Crypto Board approval + * Holds if the expression represents a protocol that requires Crypto Board approval. */ predicate isExprTls13BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -294,7 +297,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic TLS or SSL/TLS protocol + * Holds if the expression represents a generic TLS or SSL/TLS protocol. */ predicate isExprTlsBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -325,7 +328,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic SSl/TLS protocol + * Holds if the expression represents a generic SSl/TLS protocol. */ predicate isExprSslV23BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -351,7 +354,8 @@ module BoostorgAsio { //////////////////////// Dataflow ///////////////////// /** - * Abstract - Protocol value Flows to the first argument of the context constructor + * Abstract class for flows of protocol values to the first argument of a context + * constructor. */ abstract class SslContextCallAbstractConfig extends DataFlow::Configuration { bindingset[this] @@ -366,7 +370,7 @@ module BoostorgAsio { } /** - * any Protocol value Flows to the first argument of the context constructor + * Any protocol value that flows to the first argument of a context constructor. */ class SslContextCallConfig extends SslContextCallAbstractConfig { SslContextCallConfig() { this = "SslContextCallConfig" } @@ -380,7 +384,7 @@ module BoostorgAsio { } /** - * a banned protocol value Flows to the first argument of the context constructor + * A banned protocol value that flows to the first argument of a context constructor. */ class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" } @@ -395,7 +399,7 @@ module BoostorgAsio { } /** - * a TLS 1.2 protocol value Flows to the first argument of the context constructor + * A TLS 1.2 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -410,7 +414,7 @@ module BoostorgAsio { } /** - * a TLS 1.3 protocol value Flows to the first argument of the context constructor + * A TLS 1.3 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -425,7 +429,7 @@ module BoostorgAsio { } /** - * a generic TLS protocol value Flows to the first argument of the context constructor + * A generic TLS protocol value that flows to the first argument of a context constructor. */ class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" } @@ -440,7 +444,7 @@ module BoostorgAsio { } /** - * a context constructor call flows to a call calling SetOptions() + * A context constructor call that flows to a call to `SetOptions()`. */ class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" } @@ -464,7 +468,7 @@ module BoostorgAsio { } /** - * an option value flows to the 1st parameter of SetOptions() + * An option value that flows to the first parameter of a call to `SetOptions()`. */ class SslOptionConfig extends DataFlow::Configuration { SslOptionConfig() { this = "SslOptionConfig" } diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme b/cpp/ql/src/semmlecode.cpp.dbscheme index 98a075d5495..bd182f697bf 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme +++ b/cpp/ql/src/semmlecode.cpp.dbscheme @@ -731,6 +731,11 @@ class_template_argument( int index: int ref, int arg_type: @type ref ); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); is_proxy_class_for( unique int id: @usertype ref, @@ -755,6 +760,11 @@ function_template_argument( int index: int ref, int arg_type: @type ref ); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); is_variable_template(unique int id: @variable ref); variable_instantiation( @@ -766,6 +776,11 @@ variable_template_argument( int index: int ref, int arg_type: @type ref ); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); /* Fixed point types diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme.stats b/cpp/ql/src/semmlecode.cpp.dbscheme.stats index bd1964b0d4f..3a73724456a 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/src/semmlecode.cpp.dbscheme.stats @@ -1,15 +1,15 @@ @compilation -10588 +10177 @externalDataElement -72 +70 @duplication -185332 +185440 @similarity @@ -17,7 +17,7 @@ @external_package -133 +128 @svnentry @@ -25,67 +25,67 @@ @location_default -9664446 +9335283 @location_stmt -2176932 +2178211 @location_expr -9745314 +9746017 @diagnostic -76160 +73204 @file -66167 +63599 @folder -12107 +11637 @macroinvocation -40814994 +39320374 @function -3565918 +3552236 @fun_decl -3657006 +3635139 @var_decl -5579181 +5495954 @type_decl -1469165 +1413769 @namespace_decl -151627 +145743 @using -320601 +308161 @static_assert -132358 +131017 @parameter -4779409 +4724692 @membervariable -325099 +321201 @globalvariable @@ -93,47 +93,47 @@ @localvariable -527101 +521758 @enumconstant -94487 +94097 @builtintype -559 +537 @derivedtype -4572495 +4651908 @decltype -45841 +44063 @usertype -4363319 +4337028 @mangledname -532986 +514256 @type_mention -1699359 +1682135 @routinetype -444572 +436132 @ptrtomember -12180 +13227 @specifier -547 +525 @gnuattribute @@ -141,11 +141,11 @@ @stdattribute -369 +365 @declspec -58441 +57849 @msattribute @@ -153,7 +153,7 @@ @alignas -267 +257 @attribute_arg_empty @@ -161,55 +161,55 @@ @attribute_arg_token -15930 +15768 @attribute_arg_constant -111500 +111565 @attribute_arg_type -60 +58 @derivation -370309 +392220 @frienddecl -231178 +222208 @comment -1743633 +1675974 @namespace -8497 +8167 @specialnamequalifyingelement -12 +11 @namequalifier -1125621 +1116919 @value -8776796 +8788031 @initialiser -1685017 +1668506 @literal -4374193 +4381545 @errorexpr -48066 +46201 @address_of @@ -217,15 +217,15 @@ @reference_to -1077837 +1039133 @indirect -294638 +294811 @ref_indirect -1267903 +1225212 @array_to_pointer @@ -233,31 +233,31 @@ @vacuous_destructor_call -4449 +4288 @assume -3328 +3294 @parexpr -3001187 +3002950 @arithnegexpr -654789 +654792 @unaryplusexpr -206 +198 @complementexpr -28027 +28043 @notexpr -357915 +358125 @conjugation @@ -265,51 +265,51 @@ @realpartexpr -72 +70 @imagpartexpr -72 +70 @postincrexpr -43039 +43064 @postdecrexpr -5401 +5404 @preincrexpr -63954 +61508 @predecrexpr -26586 +25554 @conditionalexpr -154429 +154519 @addexpr -209503 +209626 @subexpr -134974 +135053 @mulexpr -91616 +91670 @divexpr -63973 +64010 @remexpr -4657 +4660 @jmulexpr @@ -337,59 +337,59 @@ @paddexpr -87252 +87303 @psubexpr -23151 +23165 @pdiffexpr -25868 +24865 @lshiftexpr -347564 +347768 @rshiftexpr -59286 +59321 @andexpr -236938 +237077 @orexpr -145217 +143745 @xorexpr -37281 +37303 @eqexpr -212621 +212746 @neexpr -88456 +88508 @gtexpr -43936 +43962 @ltexpr -54831 +54863 @geexpr -22361 +22374 @leexpr -213875 +214001 @minexpr @@ -401,7 +401,7 @@ @assignexpr -551713 +552037 @assignaddexpr @@ -413,15 +413,15 @@ @assignmulexpr -7597 +7302 @assigndivexpr -2297 +2208 @assignremexpr -303 +292 @assignlshiftexpr @@ -433,39 +433,39 @@ @assignandexpr -7740 +7744 @assignorexpr -18663 +18674 @assignxorexpr -21992 +22005 @assignpaddexpr -13214 +13080 @assignpsubexpr -583 +577 @andlogicalexpr -116840 +116908 @orlogicalexpr -57827 +57861 @commaexpr -10721 +10329 @subscriptexpr -165754 +165851 @virtfunptrexpr @@ -473,15 +473,15 @@ @callexpr -248513 +239197 @vastartexpr -3710 +3673 @vaargexpr -1094 +1051 @vaendexpr @@ -493,63 +493,63 @@ @varaccess -5376400 +5325591 @thisaccess -1181340 +1169367 @new_expr -29515 +28370 @delete_expr -6564 +6309 @throw_expr -23777 +22855 @condition_decl -7646 +7349 @braced_init_list -133 +128 @type_id -4899 +4708 @runtime_sizeof -281622 +281787 @runtime_alignof -1560 +1561 @sizeof_pack -267 +502 @expr_stmt -160546 +160640 @routineexpr -2309113 +2232038 @type_operand -127928 +128003 @offsetofexpr -35356 +35377 @hasassignexpr @@ -597,11 +597,11 @@ @isbaseofexpr -19 +39 @isclassexpr -6 +215 @isconvtoexpr @@ -609,15 +609,15 @@ @isemptyexpr -5 +175 @isenumexpr -3 +23 @ispodexpr -3 +11 @ispolyexpr @@ -629,7 +629,7 @@ @typescompexpr -46285 +46312 @intaddrexpr @@ -637,11 +637,11 @@ @hastrivialdestructor -97 +105 @uuidof -856 +848 @aggregateliteral @@ -649,11 +649,11 @@ @delete_array_expr -1495 +1437 @new_array_expr -5364 +5310 @foldexpr @@ -661,59 +661,59 @@ @ctordirectinit -93264 +89645 @ctorvirtualinit -6904 +6636 @ctorfieldinit -209661 +201538 @ctordelegatinginit -741 +712 @dtordirectdestruct -30828 +30111 @dtorvirtualdestruct -2698 +2594 @dtorfielddestruct -32542 +31279 @static_cast -224735 +226064 @reinterpret_cast -31207 +30891 @const_cast -5847 +5643 @dynamic_cast -1094 +1051 @c_style_cast -4242732 +4244118 @lambdaexpr -12641 +12513 @param_ref -53208 +51144 @noopexpr @@ -745,7 +745,7 @@ @istrivialexpr -2565 +2512 @isstandardlayoutexpr @@ -753,7 +753,7 @@ @istriviallycopyableexpr -48 +46 @isliteraltypeexpr @@ -813,11 +813,11 @@ @isfinalexpr -2 +175 @noexceptexpr -449 +432 @builtinshufflevector @@ -825,11 +825,11 @@ @builtinchooseexpr -7028 +7032 @builtinaddressof -4388 +4218 @vec_fill @@ -845,67 +845,67 @@ @lambdacapture -21730 +21509 @stmt_expr -1284462 +1271443 @stmt_if -524558 +524866 @stmt_while -32907 +31630 @stmt_goto -111432 +111498 @stmt_label -85508 +85558 @stmt_return -1197201 +1154730 @stmt_block -1398281 +1348007 @stmt_end_test_while -149900 +149988 @stmt_for -32387 +32059 @stmt_switch_case -281530 +281695 @stmt_switch -55225 +55258 @stmt_asm -251715 +251863 @stmt_try_block -18964 +18228 @stmt_microsoft_try -171 +169 @stmt_decl -647378 +623601 @stmt_set_vla_size @@ -917,27 +917,27 @@ @stmt_assigned_goto -9137 +9142 @stmt_empty -103681 +102630 @stmt_continue -8603 +8608 @stmt_break -232406 +232543 @stmt_range_based_for -24 +23 @stmt_handler -21888 +21666 @stmt_constexpr_if @@ -945,51 +945,51 @@ @ppd_plain_include -321707 +309224 @ppd_define -349947 +336367 @ppd_if -171077 +164439 @ppd_ifdef -66823 +64230 @ppd_ifndef -91793 +88231 @ppd_elif -22768 +21885 @ppd_else -63638 +61169 @ppd_endif -329694 +316901 @ppd_undef -21152 +20331 @ppd_line -12523 +12530 @ppd_error -48 +46 @ppd_pragma -37040 +36665 @ppd_objc_import @@ -997,7 +997,7 @@ @ppd_include_next -97 +93 @ppd_warning @@ -1005,7 +1005,7 @@ @link_target -644 +619 @xmldtd @@ -1034,15 +1034,15 @@ compilations -10588 +10177 id -10588 +10177 cwd -12 +11 @@ -1056,7 +1056,7 @@ 1 2 -10588 +10177 @@ -1072,7 +1072,7 @@ 871 872 -12 +11 @@ -1082,11 +1082,11 @@ compilation_args -394124 +394355 id -4637 +4640 num @@ -1094,7 +1094,7 @@ arg -20097 +20109 @@ -1113,7 +1113,7 @@ 87 88 -3527 +3529 88 @@ -1149,7 +1149,7 @@ 86 87 -3529 +3531 87 @@ -1322,12 +1322,12 @@ 1 2 -19123 +19134 2 2575 -974 +975 @@ -1343,7 +1343,7 @@ 1 2 -19748 +19760 2 @@ -1358,19 +1358,19 @@ compilation_compiling_files -10588 +10177 id -10588 +10177 num -12 +11 file -5373 +5164 @@ -1384,7 +1384,7 @@ 1 2 -10588 +10177 @@ -1400,7 +1400,7 @@ 1 2 -10588 +10177 @@ -1416,7 +1416,7 @@ 871 872 -12 +11 @@ -1432,7 +1432,7 @@ 442 443 -12 +11 @@ -1448,17 +1448,17 @@ 1 2 -303 +292 2 3 -5044 +4849 3 14 -24 +23 @@ -1474,7 +1474,7 @@ 1 2 -5373 +5164 @@ -1484,23 +1484,23 @@ compilation_time -42255 +40616 id -10563 +10154 num -12 +11 kind -48 +46 seconds -12375 +11965 @@ -1514,7 +1514,7 @@ 1 2 -10563 +10154 @@ -1530,7 +1530,7 @@ 4 5 -10563 +10154 @@ -1544,14 +1544,19 @@ 12 +2 +3 +58 + + 3 4 -3160 +2792 4 5 -7403 +7302 @@ -1567,7 +1572,7 @@ 869 870 -12 +11 @@ -1583,7 +1588,7 @@ 4 5 -12 +11 @@ -1597,9 +1602,9 @@ 12 -1018 -1019 -12 +1024 +1025 +11 @@ -1615,7 +1620,7 @@ 869 870 -48 +46 @@ -1631,7 +1636,7 @@ 1 2 -48 +46 @@ -1645,24 +1650,24 @@ 12 -6 -7 -12 +7 +8 +11 -9 -10 -12 +10 +11 +11 -561 -562 -12 +560 +561 +11 -597 -598 -12 +591 +592 +11 @@ -1678,27 +1683,27 @@ 1 2 -7755 +7501 2 3 -2613 +2617 3 4 -1045 +759 4 -324 -936 +8 +899 -417 -614 -24 +8 +632 +186 @@ -1714,7 +1719,7 @@ 1 2 -12375 +11965 @@ -1730,12 +1735,17 @@ 1 2 -10490 +10305 2 3 -1884 +1635 + + +3 +4 +23 @@ -1745,23 +1755,23 @@ diagnostic_for -940397 +903906 diagnostic -940397 +73204 compilation -10223 +9826 file_number -12 +11 file_number_diagnostic_number -7208 +6929 @@ -1775,7 +1785,17 @@ 1 2 -940397 +9861 + + +2 +3 +60456 + + +118 +840 +2886 @@ -1791,7 +1811,7 @@ 1 2 -940397 +73204 @@ -1807,7 +1827,12 @@ 1 2 -940397 +73181 + + +2 +3 +23 @@ -1823,37 +1848,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1869,7 +1894,7 @@ 1 2 -10223 +9826 @@ -1885,37 +1910,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1931,7 +1956,7 @@ 6265 6266 -12 +11 @@ -1947,7 +1972,7 @@ 841 842 -12 +11 @@ -1963,7 +1988,7 @@ 593 594 -12 +11 @@ -1979,47 +2004,47 @@ 1 2 -2954 +2839 2 5 -656 +630 5 6 -1057 +1016 7 14 -571 +549 15 16 -60 +58 17 18 -632 +607 18 23 -486 +467 26 40 -583 +560 42 842 -206 +198 @@ -2035,52 +2060,52 @@ 4 9 -619 +595 10 11 -1057 +1016 14 27 -571 +549 30 31 -60 +58 34 35 -632 +607 36 45 -486 +467 52 79 -583 +560 84 85 -194 +186 254 255 -2893 +2780 272 842 -109 +105 @@ -2096,7 +2121,7 @@ 1 2 -7208 +6929 @@ -2106,19 +2131,19 @@ compilation_finished -10588 +10177 id -10588 +10177 cpu_seconds -8436 +7957 elapsed_seconds -182 +186 @@ -2132,7 +2157,7 @@ 1 2 -10588 +10177 @@ -2148,7 +2173,7 @@ 1 2 -10588 +10177 @@ -2164,17 +2189,17 @@ 1 2 -7184 +6730 2 3 -850 +712 3 -12 -401 +9 +514 @@ -2190,12 +2215,12 @@ 1 2 -8023 +7560 2 3 -413 +397 @@ -2211,67 +2236,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 +11 -4 -5 -12 - - -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +27 +28 +11 53 54 -12 +11 -124 -125 -12 +120 +121 +11 -134 -135 -12 +125 +126 +11 -230 -231 -12 +233 +234 +11 -258 -259 -12 +263 +264 +11 @@ -2287,67 +2307,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 +11 -4 -5 -12 - - -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +26 +27 +11 -49 -50 -12 +51 +52 +11 -100 -101 -12 +92 +93 +11 118 119 -12 +11 -172 -173 -12 +163 +164 +11 -217 -218 -12 +215 +216 +11 @@ -2357,23 +2372,23 @@ externalData -145 +140 id -72 +70 path -12 +11 column -24 +23 value -145 +140 @@ -2387,7 +2402,7 @@ 1 2 -72 +70 @@ -2403,7 +2418,7 @@ 2 3 -72 +70 @@ -2419,7 +2434,7 @@ 2 3 -72 +70 @@ -2435,7 +2450,7 @@ 6 7 -12 +11 @@ -2451,7 +2466,7 @@ 2 3 -12 +11 @@ -2467,7 +2482,7 @@ 12 13 -12 +11 @@ -2483,7 +2498,7 @@ 6 7 -24 +23 @@ -2499,7 +2514,7 @@ 1 2 -24 +23 @@ -2515,7 +2530,7 @@ 6 7 -24 +23 @@ -2531,7 +2546,7 @@ 1 2 -145 +140 @@ -2547,7 +2562,7 @@ 1 2 -145 +140 @@ -2563,7 +2578,7 @@ 1 2 -145 +140 @@ -2573,41 +2588,41 @@ snapshotDate -12 +11 snapshotDate -12 +11 sourceLocationPrefix -12 +11 prefix -12 +11 duplicateCode -185332 +185440 id -185332 +185440 relativePath -761 +762 equivClass -76596 +76641 @@ -2621,7 +2636,7 @@ 1 2 -185332 +185440 @@ -2637,7 +2652,7 @@ 1 2 -185332 +185440 @@ -2765,27 +2780,27 @@ 1 2 -20462 +20474 2 3 -32635 +32655 3 4 -10716 +10723 4 5 -6015 +6019 5 9 -5954 +5957 9 @@ -2806,7 +2821,7 @@ 1 2 -75730 +75775 2 @@ -3122,27 +3137,27 @@ tokens -39620249 +39643528 id -279171 +279335 offset -21169 +21181 beginLine -785436 +785898 beginColumn -1302 +1303 endLine -785436 +785898 endColumn @@ -3160,72 +3175,72 @@ 100 101 -8596 +8601 101 102 -27640 +27656 102 105 -22613 +22626 105 108 -24506 +24520 108 111 -13844 +13852 111 114 -23787 +23801 114 116 -22681 +22694 116 124 -23658 +23672 124 132 -21660 +21673 132 154 -21347 +21360 154 186 -21323 +21335 186 202 -23418 +23432 202 416 -20978 +20991 416 3446 -3115 +3117 @@ -3246,47 +3261,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3302,42 +3317,42 @@ 2 26 -22933 +22946 26 31 -22318 +22331 31 32 -2642 +2643 32 33 -163572 +163668 33 51 -21310 +21323 51 61 -22472 +22485 61 80 -21058 +21071 80 132 -2863 +2865 @@ -3358,47 +3373,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3414,42 +3429,42 @@ 2 26 -21667 +21679 26 31 -24352 +24366 31 32 -1622 +1623 32 33 -163861 +163957 33 54 -22103 +22116 54 63 -20942 +20954 63 82 -21488 +21501 82 133 -3133 +3135 @@ -3465,17 +3480,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3485,37 +3500,37 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 250 -1597 +1598 251 982 -1591 +1592 986 45432 -1929 +1930 @@ -3531,17 +3546,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3551,42 +3566,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3602,47 +3617,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1886 +1887 7 12 -1837 +1838 12 15 -1640 +1641 15 23 -1591 +1592 23 68 -1609 +1610 68 161 -1591 +1592 161 @@ -3663,17 +3678,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3683,42 +3698,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3734,47 +3749,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1911 +1912 7 12 -1825 +1826 12 15 -1609 +1610 15 24 -1677 +1678 24 74 -1616 +1617 74 169 -1591 +1592 170 @@ -3795,37 +3810,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -3841,52 +3856,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -3902,47 +3917,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -3958,7 +3973,7 @@ 1 2 -785436 +785898 @@ -3974,47 +3989,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -4430,37 +4445,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -4476,52 +4491,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -4537,7 +4552,7 @@ 1 2 -785436 +785898 @@ -4553,47 +4568,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -4609,47 +4624,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -5039,23 +5054,23 @@ external_packages -133 +128 id -133 +128 namespace -12 +11 package_name -133 +128 version -133 +128 @@ -5069,7 +5084,7 @@ 1 2 -133 +128 @@ -5085,7 +5100,7 @@ 1 2 -133 +128 @@ -5101,7 +5116,7 @@ 1 2 -133 +128 @@ -5117,7 +5132,7 @@ 11 12 -12 +11 @@ -5133,7 +5148,7 @@ 11 12 -12 +11 @@ -5149,7 +5164,7 @@ 11 12 -12 +11 @@ -5165,7 +5180,7 @@ 1 2 -133 +128 @@ -5181,7 +5196,7 @@ 1 2 -133 +128 @@ -5197,7 +5212,7 @@ 1 2 -133 +128 @@ -5213,7 +5228,7 @@ 1 2 -133 +128 @@ -5229,7 +5244,7 @@ 1 2 -133 +128 @@ -5245,7 +5260,7 @@ 1 2 -133 +128 @@ -5255,15 +5270,15 @@ header_to_external_package -9093 +8740 fileid -9093 +8740 package -133 +128 @@ -5277,7 +5292,7 @@ 1 2 -9093 +8740 @@ -5293,42 +5308,42 @@ 1 2 -36 +35 2 3 -12 +11 15 16 -24 +23 63 64 -12 +11 71 72 -12 +11 85 86 -12 +11 243 244 -12 +11 251 252 -12 +11 @@ -6546,31 +6561,31 @@ locations_default -9664446 +9335283 id -9664446 +9335283 container -78275 +75237 startLine -161084 +154834 startColumn -6017 +5818 endLine -160902 +154658 endColumn -8169 +11182 @@ -6584,7 +6599,7 @@ 1 2 -9664446 +9335283 @@ -6600,7 +6615,7 @@ 1 2 -9664446 +9335283 @@ -6616,7 +6631,7 @@ 1 2 -9664446 +9335283 @@ -6632,7 +6647,7 @@ 1 2 -9664446 +9335283 @@ -6648,7 +6663,7 @@ 1 2 -9664446 +9335283 @@ -6664,62 +6679,62 @@ 1 2 -12752 +12257 2 19 -6625 +6368 19 25 -6090 +5818 25 31 -6066 +5830 31 41 -6491 +6204 41 54 -6138 +5854 54 72 -6175 +5877 72 -99 -5968 +98 +5690 -99 -137 -5944 +98 +136 +5702 -137 -221 -5895 +136 +216 +5690 -221 -431 -5871 +216 +417 +5655 -431 +417 19703 -4254 +4288 @@ -6735,62 +6750,62 @@ 1 2 -12752 +12257 2 15 -6503 +6251 15 20 -6758 +6496 20 25 -6102 +5842 25 32 -6710 +6461 32 41 -6284 +6052 41 53 -6321 +6064 53 70 -5932 +5690 70 96 -5908 +5678 96 152 -5883 +5667 152 -325 -5871 +322 +5643 -325 +324 8863 -3245 +3131 @@ -6806,62 +6821,62 @@ 1 2 -12752 +12257 2 4 -6722 +6461 4 8 -7087 +6812 8 11 -5895 +5632 11 14 -6418 +6099 14 18 -6880 +6601 18 23 -6394 +6134 23 29 -6455 +6227 29 37 -6260 +6029 37 50 -6224 +6052 50 78 -5944 +5737 78 -167 -1239 +168 +1191 @@ -6877,62 +6892,62 @@ 1 2 -12752 +12257 2 15 -6479 +6227 15 20 -6795 +6531 20 25 -6029 +5772 25 32 -6710 +6473 32 41 -6297 +6052 41 53 -6309 +6052 53 70 -6017 +5772 70 96 -5920 +5690 96 153 -5932 +5725 153 332 -5883 +5643 332 8863 -3148 +3038 @@ -6948,62 +6963,62 @@ 1 2 -12752 +12257 2 14 -6236 +5994 14 19 -6710 +6414 19 23 -6224 +5994 23 27 -6005 +5690 27 32 -6187 +5994 32 38 -6005 +5690 38 45 -6138 +5830 45 54 -5920 +5713 54 65 -5993 +5807 65 -79 -5883 +80 +5842 -79 -184 -4218 +80 +336 +4007 @@ -7019,62 +7034,62 @@ 1 2 -31193 +29982 2 3 -19802 +19034 3 4 -18234 +17527 4 5 -10260 +9861 5 6 -9129 +8775 6 7 -6734 +6473 7 9 -14344 +13787 9 13 -13943 +13390 13 30 -12350 +11871 30 112 -12119 +11637 112 -2168 -12083 +2116 +11614 -2193 +2135 6440 -887 +876 @@ -7090,42 +7105,42 @@ 1 2 -57268 +55046 2 3 -35496 +34119 3 4 -11341 +10901 4 5 -8983 +8635 5 8 -14794 +14220 8 26 -12363 +11871 26 115 -12095 +11637 115 6440 -8740 +8401 @@ -7141,57 +7156,57 @@ 1 2 -32287 +31034 2 3 -19693 +18929 3 4 -20544 +19747 4 5 -9737 +9359 5 6 -9384 +9020 6 7 -6856 +6590 7 9 -14612 +14033 9 13 -14028 +13495 13 27 -12436 +11953 27 60 -12132 +11637 60 153 -9372 +9032 @@ -7207,22 +7222,22 @@ 1 2 -119911 +115246 2 3 -18976 +18239 3 7 -13530 +13016 7 184 -8667 +8331 @@ -7238,57 +7253,57 @@ 1 2 -32311 +31057 2 3 -19584 +18824 3 4 -19024 +18286 4 5 -10247 +9850 5 6 -9409 +9043 6 7 -6637 +6379 7 9 -14636 +14068 9 13 -13700 +13168 13 28 -12144 +11673 28 -68 -12119 +69 +11813 -68 -190 -11269 +69 +258 +10668 @@ -7304,57 +7319,57 @@ 1 2 -948 +934 2 3 -1142 +1074 3 5 -534 +537 5 8 -547 +514 8 16 -474 +467 16 -38 -461 +37 +444 -39 -126 -461 +37 +119 +444 -135 -517 -461 +125 +511 +444 -553 -5009 -461 +518 +4987 +444 -5423 -19562 -461 +5021 +19113 +444 -23702 -199709 -60 +19590 +199744 +70 @@ -7370,47 +7385,47 @@ 1 2 -2589 +2500 2 3 -522 +525 3 6 -474 +455 6 15 -486 +467 15 55 -461 +444 59 -223 -461 +226 +444 229 -1196 -461 +1198 +444 -1266 +1275 2344 -461 +444 -2536 +2542 6440 -97 +93 @@ -7426,57 +7441,57 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -929 -461 +196 +829 +444 -957 -1965 -461 +851 +1958 +444 -1969 +1958 6490 -303 +327 @@ -7492,55 +7507,55 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -931 -461 +205 +828 +444 -958 -1966 -461 +851 +1962 +467 -1969 +1965 6462 303 @@ -7558,42 +7573,42 @@ 1 2 -2735 +2640 2 3 -522 +525 3 7 -547 +525 7 13 -474 +455 13 29 -498 +479 29 -51 -474 +54 +455 -51 -90 -461 +54 +109 +444 -91 +110 428 -303 +292 @@ -7609,62 +7624,62 @@ 1 2 -30670 +29480 2 3 -20240 +19455 3 4 -17979 +17281 4 5 -10430 +10025 5 6 -8898 +8553 6 7 -6868 +6601 7 9 -14368 +13811 9 13 -13992 +13437 13 30 -12302 +11824 30 111 -12144 +11649 111 -2100 -12071 +2058 +11602 -2100 +2083 6440 -936 +934 @@ -7680,42 +7695,42 @@ 1 2 -56758 +54555 2 3 -35654 +34271 3 4 -11341 +10901 4 5 -9105 +8751 5 7 -11949 +11474 7 19 -12338 +11859 19 76 -12083 +11614 76 6440 -11670 +11229 @@ -7731,22 +7746,22 @@ 1 2 -118792 +114171 2 3 -19267 +18508 3 7 -12983 +12502 7 46 -9858 +9476 @@ -7762,57 +7777,57 @@ 1 2 -31752 +30520 2 3 -20082 +19303 3 4 -20252 +19466 4 5 -9992 +9604 5 6 -9263 +8903 6 7 -6977 +6707 7 9 -14599 +14021 9 13 -14101 +13565 13 27 -12350 +11871 27 60 -12107 +11626 60 153 -9421 +9067 @@ -7828,57 +7843,57 @@ 1 2 -31801 +30567 2 3 -19973 +19197 3 4 -18745 +18017 4 5 -10490 +10083 5 6 -9263 +8903 6 7 -6710 +6449 7 9 -14526 +13963 9 13 -14174 +13612 13 29 -12350 +11871 29 71 -12132 +11602 71 -190 -10734 +258 +10387 @@ -7894,52 +7909,47 @@ 1 2 -2309 +4428 2 3 -1094 +1180 3 4 -607 +888 4 -7 -753 +6 +1004 -7 -17 -656 +6 +13 +841 -17 -49 -619 +13 +61 +841 -55 -236 -619 +61 +698 +841 -241 -4440 -619 +705 +10765 +841 -4617 -11969 -619 - - -12066 -25444 -267 +11014 +25447 +315 @@ -7955,47 +7965,42 @@ 1 2 -3257 +5106 2 3 -1033 +1285 3 4 -583 +1028 4 -9 -644 +7 +969 -9 -29 -619 +7 +33 +841 -29 -166 -619 +33 +376 +841 -172 -1667 -619 +387 +2684 +841 -1667 -2846 -619 - - -2870 +2688 6440 -170 +268 @@ -8011,52 +8016,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +899 4 -7 -741 +6 +1004 -7 -17 -632 +6 +14 +852 -17 -45 -619 +14 +57 +852 -45 -189 -619 +58 +510 +841 -192 -1191 -619 +518 +2401 +841 -1218 -2414 -619 - - -2469 +2415 4808 -243 +245 @@ -8072,42 +8072,42 @@ 1 2 -3367 +5141 2 3 -1130 +1343 3 4 -595 +1028 4 -11 -668 +7 +969 -11 +7 23 -632 +852 23 -40 -632 +47 +864 -40 -68 -632 +47 +81 +864 -68 -82 -510 +81 +83 +116 @@ -8123,52 +8123,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +911 4 -7 -741 +6 +993 -7 -17 -644 +6 +13 +841 -17 -46 -619 +13 +56 +841 -46 -194 -619 +56 +501 +841 -202 -1220 -619 +505 +2374 +841 -1252 -2470 -619 - - -2481 +2398 4808 -230 +268 @@ -8178,31 +8173,31 @@ locations_stmt -2176932 +2178211 id -2176932 +2178211 container -3078 +3080 startLine -296727 +296902 startColumn -1228 +1229 endLine -294872 +295045 endColumn -1493 +1494 @@ -8216,7 +8211,7 @@ 1 2 -2176932 +2178211 @@ -8232,7 +8227,7 @@ 1 2 -2176932 +2178211 @@ -8248,7 +8243,7 @@ 1 2 -2176932 +2178211 @@ -8264,7 +8259,7 @@ 1 2 -2176932 +2178211 @@ -8280,7 +8275,7 @@ 1 2 -2176932 +2178211 @@ -8493,7 +8488,7 @@ 38 48 -251 +252 48 @@ -8534,7 +8529,7 @@ 6 15 -251 +252 15 @@ -8681,37 +8676,37 @@ 1 2 -113847 +113914 2 3 -78993 +79039 3 4 -31327 +31345 4 6 -24942 +24957 6 16 -22619 +22632 16 129 -22275 +22288 129 222 -2722 +2723 @@ -8727,32 +8722,32 @@ 1 2 -175967 +176070 2 3 -51906 +51936 3 5 -22552 +22565 5 13 -22373 +22386 13 125 -22257 +22270 125 176 -1671 +1672 @@ -8768,32 +8763,32 @@ 1 2 -130943 +131019 2 3 -73506 +73549 3 4 -30767 +30785 4 7 -26583 +26598 7 16 -22312 +22325 16 45 -12615 +12623 @@ -8809,27 +8804,27 @@ 1 2 -192251 +192364 2 3 -47310 +47337 3 4 -21765 +21778 4 9 -23264 +23278 9 30 -12136 +12143 @@ -8845,32 +8840,32 @@ 1 2 -156444 +156536 2 3 -62371 +62408 3 4 -20782 +20794 4 9 -24659 +24674 9 30 -22398 +22411 30 73 -10071 +10077 @@ -9266,37 +9261,37 @@ 1 2 -116305 +116374 2 3 -72848 +72891 3 4 -31996 +32015 4 6 -25618 +25633 6 16 -23031 +23044 16 126 -22121 +22134 126 228 -2949 +2951 @@ -9312,27 +9307,27 @@ 1 2 -175604 +175707 2 3 -52066 +52096 3 5 -22207 +22220 5 14 -23375 +23389 14 173 -21617 +21630 @@ -9348,27 +9343,27 @@ 1 2 -194592 +194706 2 3 -42314 +42339 3 4 -20677 +20689 4 8 -22760 +22774 8 32 -14526 +14535 @@ -9384,32 +9379,32 @@ 1 2 -133173 +133251 2 3 -67871 +67910 3 4 -32611 +32630 4 7 -26503 +26518 7 16 -22183 +22196 16 46 -12529 +12536 @@ -9425,32 +9420,32 @@ 1 2 -156272 +156364 2 3 -62230 +62266 3 4 -21132 +21144 4 9 -23756 +23770 9 33 -22318 +22331 33 73 -9162 +9167 @@ -9830,15 +9825,15 @@ locations_expr -9745314 +9746017 id -9745314 +9746017 container -3559 +3563 startLine @@ -9868,7 +9863,7 @@ 1 2 -9745314 +9746017 @@ -9884,7 +9879,7 @@ 1 2 -9745314 +9746017 @@ -9900,7 +9895,7 @@ 1 2 -9745314 +9746017 @@ -9916,7 +9911,7 @@ 1 2 -9745314 +9746017 @@ -9932,7 +9927,7 @@ 1 2 -9745314 +9746017 @@ -9953,67 +9948,67 @@ 4 11 -280 +284 11 -36 -267 +37 +272 -36 -112 -270 +37 +114 +269 -112 -207 +114 +210 +269 + + +210 +328 268 -207 -326 +328 +498 268 -326 -493 -267 +499 +771 +269 -493 -760 -267 +772 +1223 +268 -760 -1208 -267 +1223 +1918 +268 -1210 -1899 -267 +1918 +3307 +268 -1900 -3251 -267 +3322 +7569 +268 -3258 -7330 -267 +7607 +160039 +268 -7359 -51115 -267 - - -51126 +170837 491727 -16 +3 @@ -10029,17 +10024,17 @@ 1 3 -300 +296 3 7 -315 +319 7 17 -271 +272 17 @@ -10049,47 +10044,47 @@ 35 59 -279 +278 59 88 -270 +271 88 138 -268 +271 138 -206 -267 +207 +271 -206 -336 +207 +339 268 -336 -525 +339 +532 268 -525 -946 -267 +532 +949 +268 -947 -2013 -267 +951 +2069 +268 -2019 +2076 142752 -248 +242 @@ -10105,67 +10100,67 @@ 1 3 -308 +307 3 7 -293 +296 7 17 -273 +274 17 -35 -267 +36 +283 -35 -51 -278 +36 +52 +287 -51 -63 -289 +52 +64 +297 -63 -73 -290 +64 +74 +279 -73 -83 +74 +84 +296 + + +84 +93 +270 + + +93 +106 282 -83 -92 -276 +106 +122 +271 -92 -104 -270 +122 +150 +268 -104 -120 -276 - - -120 -145 -270 - - -145 +150 330 -187 +153 @@ -10181,17 +10176,17 @@ 1 3 -300 +296 3 7 -312 +316 7 17 -274 +275 17 @@ -10201,17 +10196,17 @@ 35 59 -278 +277 59 89 -275 +277 89 139 -271 +273 139 @@ -10230,18 +10225,18 @@ 547 -971 -267 +973 +269 -972 -2152 -267 +975 +2167 +268 -2152 +2170 143560 -242 +239 @@ -10257,7 +10252,7 @@ 1 3 -278 +279 3 @@ -10267,57 +10262,57 @@ 7 19 -278 +281 19 -41 -268 +42 +275 -41 +42 60 -279 +272 60 -72 -267 +73 +294 -72 -83 -280 +73 +84 +277 -83 -94 -283 +84 +95 +291 -94 -105 -292 - - -105 -119 -278 - - -119 -136 +95 +106 279 -136 -162 -269 +106 +120 +282 -162 +120 +138 +275 + + +138 +166 +270 + + +166 416 -210 +190 @@ -10667,22 +10662,22 @@ 16130 -46279 +46280 29 -48722 -86671 +48729 +86681 29 -87010 -224371 +87033 +224378 29 -237409 -710014 +237411 +710028 6 @@ -10743,17 +10738,17 @@ 1424 -2061 +2063 29 -2064 -2425 +2066 +2429 29 -2427 -2796 +2429 +2797 22 @@ -11336,18 +11331,18 @@ 35 -20304 -51564 +20305 +51570 35 -54934 +54937 117747 35 -117846 -185890 +117863 +185908 35 @@ -11408,12 +11403,12 @@ 1983 -2458 +2459 35 -2468 -2637 +2470 +2640 32 @@ -11469,7 +11464,7 @@ 2070 -5989 +5990 35 @@ -11616,7 +11611,7 @@ 2067 -5989 +5990 35 @@ -11647,23 +11642,23 @@ numlines -544741 +523603 element_id -537168 +516324 num_lines -10272 +9873 num_code -7938 +7630 num_comment -4364 +4194 @@ -11677,12 +11672,12 @@ 1 2 -529679 +509126 2 7 -7488 +7197 @@ -11698,12 +11693,12 @@ 1 2 -529740 +509184 2 7 -7427 +7139 @@ -11719,12 +11714,12 @@ 1 2 -537083 +516242 2 3 -85 +81 @@ -11740,393 +11735,41 @@ 1 2 -4655 +4475 2 3 -1325 +1273 3 4 -765 +736 4 6 -838 +806 6 12 -814 +782 12 24 -778 +747 24 118 -778 +747 118 7658 -316 - - - - - - -num_lines -num_code - - -12 - - -1 -2 -4728 - - -2 -3 -1337 - - -3 -4 -802 - - -4 -6 -850 - - -6 -11 -923 - - -11 -18 -790 - - -18 -29 -790 - - -29 -32 -48 - - - - - - -num_lines -num_comment - - -12 - - -1 -2 -4716 - - -2 -3 -1337 - - -3 -4 -826 - - -4 -6 -838 - - -6 -10 -802 - - -10 -16 -899 - - -16 -26 -814 - - -26 -27 -36 - - - - - - -num_code -element_id - - -12 - - -1 -2 -3184 - - -2 -3 -1239 - - -3 -4 -632 - - -4 -6 -607 - - -6 -10 -619 - - -10 -21 -619 - - -21 -67 -595 - - -68 -7861 -437 - - - - - - -num_code -num_lines - - -12 - - -1 -2 -3209 - - -2 -3 -1264 - - -3 -4 -644 - - -4 -6 -607 - - -6 -10 -692 - - -10 -21 -644 - - -21 -34 -607 - - -34 -42 -267 - - - - - - -num_code -num_comment - - -12 - - -1 -2 -3233 - - -2 -3 -1227 - - -3 -4 -680 - - -4 -6 -619 - - -6 -10 -680 - - -10 -19 -668 - - -19 -28 -595 - - -28 -33 -230 - - - - - - -num_comment -element_id - - -12 - - -1 -2 -2030 - - -2 -3 -559 - - -3 -4 -328 - - -4 -7 -340 - - -7 -14 -340 - - -14 -38 -328 - - -39 -280 -328 - - -283 -35679 -109 - - - - - - -num_comment -num_lines - - -12 - - -1 -2 -2042 - - -2 -3 -571 - - -3 -5 -389 - - -5 -8 -364 - - -8 -18 -364 - - -18 -58 -328 - - -61 -118 303 @@ -12134,6 +11777,358 @@ +num_lines +num_code + + +12 + + +1 +2 +4545 + + +2 +3 +1285 + + +3 +4 +771 + + +4 +6 +817 + + +6 +11 +888 + + +11 +18 +759 + + +18 +29 +759 + + +29 +32 +46 + + + + + + +num_lines +num_comment + + +12 + + +1 +2 +4533 + + +2 +3 +1285 + + +3 +4 +794 + + +4 +6 +806 + + +6 +10 +771 + + +10 +16 +864 + + +16 +26 +782 + + +26 +27 +35 + + + + + + +num_code +element_id + + +12 + + +1 +2 +3061 + + +2 +3 +1191 + + +3 +4 +607 + + +4 +6 +584 + + +6 +10 +595 + + +10 +21 +595 + + +21 +67 +572 + + +68 +7861 +420 + + + + + + +num_code +num_lines + + +12 + + +1 +2 +3084 + + +2 +3 +1215 + + +3 +4 +619 + + +4 +6 +584 + + +6 +10 +666 + + +10 +21 +619 + + +21 +34 +584 + + +34 +42 +257 + + + + + + +num_code +num_comment + + +12 + + +1 +2 +3108 + + +2 +3 +1180 + + +3 +4 +654 + + +4 +6 +595 + + +6 +10 +654 + + +10 +19 +642 + + +19 +28 +572 + + +28 +33 +222 + + + + + + +num_comment +element_id + + +12 + + +1 +2 +1951 + + +2 +3 +537 + + +3 +4 +315 + + +4 +7 +327 + + +7 +14 +327 + + +14 +38 +315 + + +39 +280 +315 + + +283 +35679 +105 + + + + + + +num_comment +num_lines + + +12 + + +1 +2 +1963 + + +2 +3 +549 + + +3 +5 +373 + + +5 +8 +350 + + +8 +18 +350 + + +18 +58 +315 + + +61 +118 +292 + + + + + + num_comment num_code @@ -12143,37 +12138,37 @@ 1 2 -2042 +1963 2 3 -571 +549 3 5 -389 +373 5 8 -364 +350 8 17 -340 +327 17 52 -328 +315 56 108 -328 +315 @@ -12183,31 +12178,31 @@ diagnostics -76160 +73204 id -76160 +73204 severity -36 +35 error_tag -97 +93 error_message -121 +116 full_error_message -65948 +63389 location -145 +140 @@ -12221,7 +12216,7 @@ 1 2 -76160 +73204 @@ -12237,7 +12232,7 @@ 1 2 -76160 +73204 @@ -12253,7 +12248,7 @@ 1 2 -76160 +73204 @@ -12269,7 +12264,7 @@ 1 2 -76160 +73204 @@ -12285,7 +12280,7 @@ 1 2 -76160 +73204 @@ -12301,17 +12296,17 @@ 1 2 -12 +11 2 3 -12 +11 6262 6263 -12 +11 @@ -12327,12 +12322,12 @@ 1 2 -24 +23 6 7 -12 +11 @@ -12348,12 +12343,12 @@ 1 2 -24 +23 8 9 -12 +11 @@ -12369,17 +12364,17 @@ 1 2 -12 +11 2 3 -12 +11 5422 5423 -12 +11 @@ -12395,17 +12390,17 @@ 1 2 -12 +11 2 3 -12 +11 9 10 -12 +11 @@ -12421,32 +12416,32 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12462,7 +12457,7 @@ 1 2 -97 +93 @@ -12478,12 +12473,12 @@ 1 2 -85 +81 3 4 -12 +11 @@ -12499,27 +12494,27 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 4996 4997 -12 +11 @@ -12535,17 +12530,17 @@ 1 2 -60 +58 2 3 -24 +23 5 6 -12 +11 @@ -12561,42 +12556,42 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12612,7 +12607,7 @@ 1 2 -121 +116 @@ -12628,7 +12623,7 @@ 1 2 -121 +116 @@ -12644,37 +12639,37 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 4996 4997 -12 +11 @@ -12690,17 +12685,17 @@ 1 2 -85 +81 2 3 -24 +23 5 6 -12 +11 @@ -12716,12 +12711,12 @@ 1 2 -65936 +63377 841 842 -12 +11 @@ -12737,7 +12732,7 @@ 1 2 -65948 +63389 @@ -12753,7 +12748,7 @@ 1 2 -65948 +63389 @@ -12769,7 +12764,7 @@ 1 2 -65948 +63389 @@ -12785,7 +12780,7 @@ 1 2 -65948 +63389 @@ -12801,12 +12796,12 @@ 1 2 -133 +128 6254 6255 -12 +11 @@ -12822,7 +12817,7 @@ 1 2 -145 +140 @@ -12838,12 +12833,12 @@ 1 2 -133 +128 3 4 -12 +11 @@ -12859,12 +12854,12 @@ 1 2 -133 +128 5 6 -12 +11 @@ -12880,12 +12875,12 @@ 1 2 -133 +128 5414 5415 -12 +11 @@ -12895,27 +12890,27 @@ files -66167 +63599 id -66167 +63599 name -66167 +63599 simple -45148 +43397 ext -109 +105 fromSource -12 +11 @@ -12929,7 +12924,7 @@ 1 2 -66167 +63599 @@ -12945,7 +12940,7 @@ 1 2 -66167 +63599 @@ -12961,7 +12956,7 @@ 1 2 -66167 +63599 @@ -12977,7 +12972,7 @@ 1 2 -66167 +63599 @@ -12993,7 +12988,7 @@ 1 2 -66167 +63599 @@ -13009,7 +13004,7 @@ 1 2 -66167 +63599 @@ -13025,7 +13020,7 @@ 1 2 -66167 +63599 @@ -13041,7 +13036,7 @@ 1 2 -66167 +63599 @@ -13057,22 +13052,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13088,22 +13083,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13119,17 +13114,17 @@ 1 2 -40322 +38758 2 3 -4193 +4031 3 6 -632 +607 @@ -13145,7 +13140,7 @@ 1 2 -45148 +43397 @@ -13161,47 +13156,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13217,47 +13212,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13273,47 +13268,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 75 76 -12 +11 112 113 -12 +11 428 429 -12 +11 658 659 -12 +11 2838 2839 -12 +11 @@ -13329,7 +13324,7 @@ 1 2 -109 +105 @@ -13345,7 +13340,7 @@ 5443 5444 -12 +11 @@ -13361,7 +13356,7 @@ 5443 5444 -12 +11 @@ -13377,7 +13372,7 @@ 3714 3715 -12 +11 @@ -13393,7 +13388,7 @@ 9 10 -12 +11 @@ -13403,19 +13398,19 @@ folders -12107 +11637 id -12107 +11637 name -12107 +11637 simple -3476 +3341 @@ -13429,7 +13424,7 @@ 1 2 -12107 +11637 @@ -13445,7 +13440,7 @@ 1 2 -12107 +11637 @@ -13461,7 +13456,7 @@ 1 2 -12107 +11637 @@ -13477,7 +13472,7 @@ 1 2 -12107 +11637 @@ -13493,27 +13488,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13529,27 +13524,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13559,15 +13554,15 @@ containerparent -78250 +75214 parent -12107 +11637 child -78250 +75214 @@ -13581,42 +13576,42 @@ 1 2 -5506 +5293 2 3 -1568 +1507 3 4 -668 +642 4 6 -1118 +1074 6 10 -899 +864 10 14 -960 +923 14 30 -923 +888 30 153 -461 +444 @@ -13632,7 +13627,7 @@ 1 2 -78250 +75214 @@ -13642,23 +13637,23 @@ fileannotations -5688625 +5467887 id -5348 +5141 kind -24 +23 name -60186 +57851 value -49318 +47404 @@ -13672,12 +13667,12 @@ 1 2 -145 +140 2 3 -5202 +5001 @@ -13693,62 +13688,62 @@ 1 96 -401 +385 96 219 -401 +385 221 285 -401 +385 285 444 -401 +385 445 521 -401 +385 526 619 -425 +408 619 708 -401 +385 708 895 -401 +385 896 928 -97 +93 930 931 -1531 +1472 1076 1667 -401 +385 1689 2272 -85 +81 @@ -13764,57 +13759,57 @@ 1 108 -401 +385 108 269 -401 +385 269 356 -401 +385 371 630 -401 +385 630 729 -401 +385 733 948 -401 +385 948 1062 -401 +385 1079 1494 -279 +268 1495 1496 -1531 +1472 1496 1865 -401 +385 1963 4058 -328 +315 @@ -13830,12 +13825,12 @@ 428 429 -12 +11 440 441 -12 +11 @@ -13851,12 +13846,12 @@ 2 3 -12 +11 4949 4950 -12 +11 @@ -13872,12 +13867,12 @@ 1 2 -12 +11 4057 4058 -12 +11 @@ -13893,62 +13888,62 @@ 1 2 -9871 +9487 2 3 -6491 +6239 3 6 -4996 +4802 6 8 -4935 +4743 8 14 -4850 +4662 14 18 -4424 +4253 18 21 -4619 +4440 21 34 -4862 +4673 34 128 -4813 +4627 129 236 -4595 +4416 236 395 -4558 +4381 395 440 -1167 +1121 @@ -13964,7 +13959,7 @@ 1 2 -60186 +57851 @@ -13980,62 +13975,62 @@ 1 2 -11038 +10609 2 3 -8728 +8389 3 4 -2808 +2699 4 6 -4352 +4183 6 10 -5470 +5258 10 14 -3586 +3446 14 17 -4643 +4463 17 22 -4643 +4463 22 40 -4558 +4381 40 83 -4582 +4405 83 163 -4534 +4358 164 1933 -1239 +1191 @@ -14051,67 +14046,67 @@ 1 2 -7524 +7232 2 5 -2419 +2325 5 8 -3573 +3435 8 21 -3804 +3657 21 23 -2735 +2629 23 25 -4461 +4288 25 40 -3586 +3446 40 195 -3890 +3739 195 207 -3902 +3750 207 273 -4048 +3891 273 327 -3744 +3598 328 407 -4315 +4148 407 441 -1312 +1261 @@ -14127,12 +14122,12 @@ 1 2 -49306 +47393 2 3 -12 +11 @@ -14148,67 +14143,67 @@ 1 2 -7549 +7256 2 5 -2795 +2687 5 8 -3610 +3470 8 16 -4060 +3902 16 18 -3343 +3213 18 21 -4072 +3914 21 31 -4461 +4288 31 42 -4023 +3867 42 54 -3768 +3622 54 81 -3780 +3633 81 109 -3829 +3680 109 133 -3756 +3610 133 149 -267 +257 @@ -14218,15 +14213,15 @@ inmacroexpansion -57126596 +57160160 id -15544516 +15553649 inv -2493763 +2495229 @@ -14240,42 +14235,42 @@ 1 2 -3895411 +3897700 2 3 -2466113 +2467562 3 4 -2018102 +2019287 4 5 -1769908 +1770948 5 6 -1845270 +1846354 6 7 -884925 +885445 7 8 -1535759 +1536661 8 6265 -1129025 +1129688 @@ -14291,52 +14286,52 @@ 1 2 -651228 +651611 2 3 -350884 +351091 3 4 -145822 +145908 4 5 -276335 +276498 5 8 -230677 +230812 8 11 -202111 +202230 11 19 -210471 +210594 19 34 -192538 +192651 34 167 -188020 +188130 167 153127 -45673 +45699 @@ -14346,15 +14341,15 @@ affectedbymacroexpansion -35527526 +35548400 id -4083475 +4085874 inv -3282712 +3284641 @@ -14368,42 +14363,42 @@ 1 2 -1341531 +1342319 2 3 -719304 +719727 3 4 -682963 +683364 4 6 -320945 +321133 6 10 -313534 +313718 10 24 -308059 +308240 24 64 -309945 +310127 64 9803 -87190 +87242 @@ -14419,72 +14414,72 @@ 1 2 -253184 +253333 2 3 -209979 +210102 3 4 -202347 +202466 4 5 -258125 +258276 5 6 -301422 +301599 6 7 -247881 +248027 7 8 -231148 +231284 8 9 -228002 +228136 9 10 -182499 +182606 10 12 -285679 +285847 12 16 -297410 +297584 16 23 -275398 +275560 23 60 -248963 +249109 60 526 -60669 +60704 @@ -14494,23 +14489,23 @@ macroinvocations -40814994 +39320374 id -40814994 +39320374 macro_id -89374 +85906 location -836970 +804492 kind -24 +23 @@ -14524,7 +14519,7 @@ 1 2 -40814994 +39320374 @@ -14540,7 +14535,7 @@ 1 2 -40814994 +39320374 @@ -14556,7 +14551,7 @@ 1 2 -40814994 +39320374 @@ -14572,52 +14567,52 @@ 1 2 -19267 +18286 2 3 -16946 +16475 3 4 -3744 +3598 4 6 -7925 +7630 6 11 -7658 +7326 11 21 -7160 +6823 21 41 -6758 +6555 41 -104 -6710 +107 +6485 -104 -454 -6710 +107 +450 +6449 -454 -201153 -6491 +453 +201240 +6274 @@ -14633,37 +14628,37 @@ 1 2 -47483 +45640 2 3 -11803 +11345 3 4 -5895 +5667 4 6 -7682 +7384 6 13 -7403 +7115 13 65 -6734 +6473 65 3614 -2370 +2278 @@ -14679,12 +14674,12 @@ 1 2 -82566 +79362 2 3 -6807 +6543 @@ -14700,42 +14695,42 @@ 1 2 -314219 +299713 2 3 -186394 +180341 3 4 -44431 +42999 4 5 -58533 +56378 5 8 -67687 +65247 8 16 -64113 +61777 16 46 -64830 +62536 46 -262302 -36761 +262546 +35498 @@ -14751,12 +14746,12 @@ 1 2 -783044 +752659 2 353 -53925 +51833 @@ -14772,7 +14767,7 @@ 1 2 -836970 +804492 @@ -14788,12 +14783,12 @@ 37566 37567 -12 +11 -3319916 -3319917 -12 +3327545 +3327546 +11 @@ -14809,12 +14804,12 @@ 2199 2200 -12 +11 5713 5714 -12 +11 @@ -14830,12 +14825,12 @@ 6537 6538 -12 +11 62313 62314 -12 +11 @@ -14845,15 +14840,15 @@ macroparent -35822215 +34476404 id -35822215 +34476404 parent_id -27895299 +26856682 @@ -14867,7 +14862,7 @@ 1 2 -35822215 +34476404 @@ -14883,17 +14878,17 @@ 1 2 -21477676 +20687700 2 3 -5474478 +5262423 3 88 -943144 +906558 @@ -14903,15 +14898,15 @@ macrolocationbind -4016679 +4019039 id -2801506 +2803152 location -2004363 +2005541 @@ -14925,22 +14920,22 @@ 1 2 -2200726 +2202019 2 3 -339324 +339524 3 7 -231800 +231936 7 57 -29655 +29673 @@ -14956,22 +14951,22 @@ 1 2 -1602305 +1603246 2 3 -171008 +171108 3 8 -155504 +155595 8 723 -75546 +75590 @@ -14981,19 +14976,19 @@ macro_argument_unexpanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -345935 +332512 @@ -15007,22 +15002,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15038,22 +15033,22 @@ 1 2 -8880284 +8550795 2 3 -13152746 +12678071 3 4 -6885304 +6640869 4 67 -2213625 +2138677 @@ -15069,17 +15064,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15095,17 +15090,17 @@ 2 3 -705 +677 13 1002 -60 +58 6617 19688 -36 +35 @@ -15121,62 +15116,62 @@ 1 2 -42535 +39868 2 3 -69291 +64826 3 4 -15621 +15435 4 5 -46376 +44296 5 8 -26513 +26980 8 12 -15560 +15447 12 16 -24531 +23275 16 22 -26403 +25414 22 -42 -26257 +41 +25075 -42 -113 -25978 +41 +101 +24970 -113 -51881 -25953 +101 +4363 +24958 -51881 -580841 -911 +4608 +581891 +1963 @@ -15192,17 +15187,17 @@ 1 2 -250082 +240378 2 3 -84450 +81173 3 9 -11402 +10960 @@ -15212,19 +15207,19 @@ macro_argument_expanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -209491 +201362 @@ -15238,22 +15233,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15269,22 +15264,22 @@ 1 2 -12795323 +12315365 2 3 -11169279 +10770085 3 4 -5961987 +5753415 4 9 -1205370 +1169546 @@ -15300,17 +15295,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15326,17 +15321,17 @@ 1 2 -692 +666 2 75 -60 +58 867 13964 -48 +46 @@ -15352,62 +15347,57 @@ 1 2 -25820 +23871 2 3 -42583 +40791 3 4 -6758 +6636 4 -5 -15791 - - -5 6 -3367 +18450 6 7 -24555 +23743 7 9 -16702 +16475 9 15 -19146 +17597 15 31 -15851 +15984 31 -87 -15912 +86 +15108 -87 -393 -15742 +86 +365 +15225 -396 -1164221 -7257 +365 +1165688 +7478 @@ -15423,22 +15413,22 @@ 1 2 -105651 +101551 2 3 -87976 +84562 3 6 -15779 +15166 6 66 -85 +81 @@ -15448,19 +15438,19 @@ functions -3565918 +3552236 id -3565918 +3552236 name -315848 +303954 kind -85 +81 @@ -15474,7 +15464,7 @@ 1 2 -3565918 +3552236 @@ -15490,7 +15480,7 @@ 1 2 -3565918 +3552236 @@ -15506,27 +15496,27 @@ 1 2 -214682 +206387 2 3 -31266 +29924 3 5 -28360 +27435 5 13 -23826 +23100 13 -109484 -17711 +118759 +17106 @@ -15542,12 +15532,12 @@ 1 2 -314231 +302400 2 3 -1616 +1554 @@ -15563,37 +15553,37 @@ 32 33 -12 +11 -477 -478 -12 +478 +479 +11 2735 2736 -12 +11 -5928 -5929 -12 +6052 +6053 +11 -43779 -43780 -12 +43879 +43880 +11 -108979 -108980 -12 +109948 +109949 +11 -131406 -131407 -12 +140883 +140884 +11 @@ -15609,37 +15599,37 @@ 11 12 -12 +11 42 43 -12 +11 -228 -229 -12 +229 +230 +11 -1485 -1486 -12 +1494 +1495 +11 2735 2736 -12 +11 -2858 -2859 -12 +2879 +2880 +11 18756 18757 -12 +11 @@ -15649,15 +15639,15 @@ function_entry_point -1068501 +1030977 id -1065255 +1027857 entry_point -1068501 +1030977 @@ -15671,12 +15661,12 @@ 1 2 -1062313 +1025030 2 9 -2941 +2827 @@ -15692,7 +15682,7 @@ 1 2 -1068501 +1030977 @@ -15702,15 +15692,15 @@ function_return_type -3577065 +3562951 id -3565347 +3551686 return_type -1033588 +1048715 @@ -15724,12 +15714,12 @@ 1 2 -3554126 +3540901 2 6 -11220 +10784 @@ -15745,17 +15735,17 @@ 1 2 -319945 +309177 2 3 -649566 +677865 3 -81742 -64076 +82133 +61671 @@ -15765,60 +15755,60 @@ purefunctions -21018 +20805 id -21018 +20805 function_deleted -51251 +49379 id -51251 +49379 function_defaulted -9554 +9184 id -9554 +9184 fun_decls -3668324 +3646017 id -3657006 +3635139 function -3484737 +3469555 type_id -1026294 +1041634 name -281968 +271389 location -875943 +843835 @@ -15832,7 +15822,7 @@ 1 2 -3657006 +3635139 @@ -15848,12 +15838,12 @@ 1 2 -3646053 +3624611 2 6 -10952 +10527 @@ -15869,7 +15859,7 @@ 1 2 -3657006 +3635139 @@ -15885,7 +15875,7 @@ 1 2 -3657006 +3635139 @@ -15901,12 +15891,12 @@ 1 2 -3343699 +3333988 2 9 -141038 +135566 @@ -15922,12 +15912,12 @@ 1 2 -3466345 +3451876 2 6 -18392 +17678 @@ -15943,7 +15933,7 @@ 1 2 -3484737 +3469555 @@ -15959,12 +15949,12 @@ 1 2 -3389832 +3378332 2 9 -94905 +91222 @@ -15980,17 +15970,17 @@ 1 2 -305953 +295716 2 3 -648059 +676381 3 -87017 -72282 +87408 +69535 @@ -16006,17 +15996,17 @@ 1 2 -318972 +308231 2 3 -644096 +672572 3 -80918 -63225 +81309 +60830 @@ -16032,12 +16022,12 @@ 1 2 -956638 +974669 2 -7429 -69656 +7459 +66965 @@ -16053,17 +16043,17 @@ 1 2 -921129 +940538 2 5 -81642 +78474 5 -22296 -23522 +22349 +22621 @@ -16079,32 +16069,32 @@ 1 2 -169351 +162826 2 3 -32554 +31420 3 4 -18866 +17994 4 7 -25650 +24841 7 19 -21261 +20518 19 -109747 -14283 +119022 +13787 @@ -16120,32 +16110,32 @@ 1 2 -181155 +174172 2 3 -31412 +30099 3 4 -16654 +16171 4 7 -22623 +21862 7 -26 -21383 +25 +20366 -26 -109468 -8740 +25 +118743 +8716 @@ -16161,17 +16151,17 @@ 1 2 -246046 +236860 2 5 -23170 +22271 5 -56245 -12752 +60936 +12257 @@ -16187,27 +16177,27 @@ 1 2 -180486 +173599 2 3 -47823 +46213 3 4 -18040 +17340 4 8 -22696 +21815 8 -8793 -12922 +8910 +12420 @@ -16223,27 +16213,27 @@ 1 2 -589769 +567012 2 3 -147895 +142319 3 5 -69790 +67350 5 -179 -65766 +141 +63307 -179 -3027 -2723 +142 +3039 +3844 @@ -16259,22 +16249,22 @@ 1 2 -602727 +579468 2 3 -164743 +158514 3 9 -69753 +67747 9 -3027 -38718 +3039 +38103 @@ -16290,17 +16280,17 @@ 1 2 -773854 +744445 2 4 -68209 +65890 4 -1514 -33879 +1520 +33500 @@ -16316,12 +16306,12 @@ 1 2 -848299 +817018 2 134 -27643 +26816 @@ -16331,22 +16321,22 @@ fun_def -1296860 +1250592 id -1296860 +1250592 fun_specialized -6505 +6439 id -6505 +6439 @@ -16364,11 +16354,11 @@ fun_decl_specifiers -512313 +512614 id -274687 +274848 name @@ -16386,17 +16376,17 @@ 1 2 -72048 +72090 2 3 -167651 +167750 3 4 -34987 +35007 @@ -16583,26 +16573,26 @@ fun_decl_empty_throws -1416734 +1471304 fun_decl -1416734 +1471304 fun_decl_noexcept -16569 +15937 fun_decl -15693 +15096 constant -16435 +15809 @@ -16616,12 +16606,12 @@ 1 2 -14818 +14255 2 3 -875 +841 @@ -16637,12 +16627,12 @@ 1 2 -16301 +15680 2 3 -133 +128 @@ -16652,26 +16642,26 @@ fun_decl_empty_noexcept -364559 +350681 fun_decl -364559 +350681 fun_decl_typedef_type -194 +186 fun_decl -194 +186 typedeftype_id -97 +93 @@ -16685,7 +16675,7 @@ 1 2 -194 +186 @@ -16701,7 +16691,7 @@ 2 3 -97 +93 @@ -16711,19 +16701,19 @@ param_decl_bind -4830661 +4766932 id -4830661 +4766932 index -389 +373 fun_decl -3158896 +3153051 @@ -16737,7 +16727,7 @@ 1 2 -4830661 +4766932 @@ -16753,7 +16743,7 @@ 1 2 -4830661 +4766932 @@ -16769,57 +16759,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16835,57 +16825,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16901,22 +16891,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16932,22 +16922,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16957,27 +16947,27 @@ var_decls -5602108 +5518014 id -5579181 +5495954 variable -5340611 +5266618 type_id -2038268 +2068405 name -139592 +134175 location -1358468 +1305755 @@ -16991,7 +16981,7 @@ 1 2 -5579181 +5495954 @@ -17007,12 +16997,12 @@ 1 2 -5556716 +5474337 2 7 -22465 +21616 @@ -17028,7 +17018,7 @@ 1 2 -5579181 +5495954 @@ -17044,12 +17034,12 @@ 1 2 -5579132 +5495907 2 3 -48 +46 @@ -17065,12 +17055,12 @@ 1 2 -5146145 +5079674 2 9 -194466 +186943 @@ -17086,12 +17076,12 @@ 1 2 -5290709 +5218605 2 7 -49902 +48012 @@ -17107,12 +17097,12 @@ 1 2 -5321866 +5248600 2 3 -18745 +18017 @@ -17128,12 +17118,12 @@ 1 2 -5225490 +5155963 2 9 -115121 +110654 @@ -17149,22 +17139,22 @@ 1 2 -1580700 +1627085 2 3 -244952 +236522 3 -9 -154629 +10 +155430 -9 -5708 -57986 +10 +5721 +49367 @@ -17180,22 +17170,22 @@ 1 2 -1607080 +1652441 2 3 -234777 +226741 3 -11 -155359 +13 +156353 -11 -5254 -41052 +13 +5267 +32869 @@ -17211,17 +17201,17 @@ 1 2 -1850925 +1888086 2 5 -162458 +156341 5 770 -24884 +23977 @@ -17237,17 +17227,17 @@ 1 2 -1771751 +1811867 2 4 -165132 +159052 4 3604 -101384 +97485 @@ -17263,42 +17253,42 @@ 1 2 -58861 +56530 2 3 -20860 +20039 3 4 -12290 +11801 4 6 -12715 +12268 6 10 -11524 +11088 10 22 -10673 +10270 22 255 -10490 +10083 263 -149390 -2176 +159500 +2091 @@ -17314,37 +17304,37 @@ 1 2 -62277 +59814 2 3 -20118 +19314 3 4 -13359 +12841 4 6 -11949 +11532 6 11 -11499 +11077 11 28 -10515 +10095 28 -148426 -9871 +158536 +9499 @@ -17360,32 +17350,32 @@ 1 2 -84973 +81606 2 3 -18149 +17445 3 4 -9676 +9347 4 7 -11706 +11275 7 28 -10576 +10165 28 -111448 -4510 +120730 +4335 @@ -17401,32 +17391,32 @@ 1 2 -80329 +77212 2 3 -21273 +20448 3 4 -7780 +7478 4 7 -12423 +11941 7 21 -10563 +10154 21 9993 -7220 +6940 @@ -17442,22 +17432,22 @@ 1 2 -1008108 +967927 2 3 -144734 +139422 3 6 -124044 +119546 6 -114124 -81581 +123459 +78860 @@ -17473,22 +17463,22 @@ 1 2 -1060320 +1018112 2 3 -107961 +103970 3 6 -111863 +107943 6 -113877 -78323 +123212 +75728 @@ -17504,17 +17494,17 @@ 1 2 -1166129 +1119863 2 3 -93045 +89797 3 -104379 -99293 +113652 +96095 @@ -17530,12 +17520,12 @@ 1 2 -1348524 +1296197 2 52 -9943 +9558 @@ -17545,11 +17535,11 @@ var_def -2573394 +2477557 id -2573394 +2477557 @@ -17619,19 +17609,19 @@ type_decls -1469165 +1413769 id -1469165 +1413769 type_id -1433996 +1379965 location -1203571 +1156868 @@ -17645,7 +17635,7 @@ 1 2 -1469165 +1413769 @@ -17661,7 +17651,7 @@ 1 2 -1469165 +1413769 @@ -17677,12 +17667,12 @@ 1 2 -1408431 +1355392 2 24 -25564 +24572 @@ -17698,12 +17688,12 @@ 1 2 -1409866 +1356771 2 24 -24130 +23194 @@ -17719,12 +17709,12 @@ 1 2 -1142582 +1098234 2 469 -60988 +58633 @@ -17740,12 +17730,12 @@ 1 2 -1144223 +1099812 2 469 -59347 +57056 @@ -17755,45 +17745,45 @@ type_def -1035654 +995467 id -1035654 +995467 type_decl_top -297552 +286006 type_decl -297552 +286006 namespace_decls -151627 +145743 id -151627 +145743 namespace_id -8485 +8155 location -135422 +130167 bodylocation -135787 +130518 @@ -17807,7 +17797,7 @@ 1 2 -151627 +145743 @@ -17823,7 +17813,7 @@ 1 2 -151627 +145743 @@ -17839,7 +17829,7 @@ 1 2 -151627 +145743 @@ -17855,42 +17845,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17906,42 +17896,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17957,42 +17947,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3742 -158 +151 @@ -18008,12 +17998,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18029,12 +18019,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18050,12 +18040,12 @@ 1 2 -134595 +129373 2 3 -826 +794 @@ -18071,12 +18061,12 @@ 1 2 -126900 +121976 2 11 -8886 +8541 @@ -18092,12 +18082,12 @@ 1 2 -126900 +121976 2 9 -8886 +8541 @@ -18113,12 +18103,12 @@ 1 2 -135349 +130097 2 5 -437 +420 @@ -18128,19 +18118,19 @@ usings -320601 +308161 id -320601 +308161 element_id -49002 +47101 location -26464 +25437 @@ -18154,7 +18144,7 @@ 1 2 -320601 +308161 @@ -18170,7 +18160,7 @@ 1 2 -320601 +308161 @@ -18186,17 +18176,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18212,17 +18202,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18238,22 +18228,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18269,22 +18259,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18294,15 +18284,15 @@ using_container -485187 +466360 parent -8667 +8331 child -301029 +289348 @@ -18316,47 +18306,47 @@ 1 2 -3379 +3248 2 3 -559 +537 3 6 -668 +642 6 15 -656 +630 16 31 -705 +677 31 143 -291 +280 178 179 -1397 +1343 179 182 -765 +736 182 501 -243 +233 @@ -18372,22 +18362,22 @@ 1 2 -217478 +209039 2 3 -55773 +53609 3 6 -22659 +21780 6 47 -5117 +4919 @@ -18397,23 +18387,23 @@ static_asserts -132358 +131017 id -132358 +131017 condition -132358 +131017 message -30094 +29789 location -16938 +16766 @@ -18427,7 +18417,7 @@ 1 2 -132358 +131017 @@ -18443,7 +18433,7 @@ 1 2 -132358 +131017 @@ -18459,7 +18449,7 @@ 1 2 -132358 +131017 @@ -18475,7 +18465,7 @@ 1 2 -132358 +131017 @@ -18491,7 +18481,7 @@ 1 2 -132358 +131017 @@ -18507,7 +18497,7 @@ 1 2 -132358 +131017 @@ -18523,32 +18513,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18564,32 +18554,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18605,12 +18595,12 @@ 1 2 -27912 +27629 2 33 -2181 +2159 @@ -18626,32 +18616,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18661,12 +18651,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18682,32 +18672,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18717,12 +18707,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18738,22 +18728,22 @@ 1 2 -4475 +4429 2 3 -6063 +6002 3 4 -6208 +6145 4 7 -191 +189 @@ -18763,23 +18753,23 @@ params -4803552 +4749557 id -4779409 +4724692 function -3118318 +3117564 index -389 +373 type_id -1865866 +1906163 @@ -18793,12 +18783,12 @@ 1 2 -4778668 +4723979 2 69 -741 +712 @@ -18814,7 +18804,7 @@ 1 2 -4779409 +4724692 @@ -18830,12 +18820,12 @@ 1 2 -4757747 +4702211 2 7 -21662 +22481 @@ -18851,22 +18841,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18882,22 +18872,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18913,22 +18903,22 @@ 1 2 -2314438 +2335471 2 3 -493113 +480884 3 5 -270978 +262941 5 20 -39787 +38267 @@ -18944,57 +18934,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256345 -256346 -12 +266636 +266637 +11 @@ -19010,57 +19000,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256516 -256517 -12 +266807 +266808 +11 @@ -19076,57 +19066,57 @@ 1 2 -158 +151 3 7 -24 +23 8 20 -24 +23 36 40 -24 +23 42 45 -24 +23 61 105 -24 +23 173 257 -24 +23 406 661 -24 +23 1178 2710 -24 +23 -7491 -16702 -24 +7492 +16795 +23 -135733 -135734 -12 +145286 +145287 +11 @@ -19142,22 +19132,22 @@ 1 2 -1495095 +1547921 2 3 -199608 +193171 3 -13 -141671 +18 +144002 -13 -5275 -29491 +18 +5288 +21067 @@ -19173,22 +19163,22 @@ 1 2 -1517195 +1569164 2 3 -187245 +181276 3 -17 -140893 +25 +143324 -17 -4798 -20532 +25 +4811 +12397 @@ -19204,12 +19194,12 @@ 1 2 -1751170 +1795906 2 33 -114695 +110257 @@ -19219,15 +19209,15 @@ overrides -161127 +159494 new -126169 +124890 old -15666 +15507 @@ -19241,12 +19231,12 @@ 1 2 -91218 +90293 2 3 -34944 +34590 3 @@ -19267,37 +19257,37 @@ 1 2 -8232 +8148 2 3 -2043 +2022 3 4 -883 +874 4 5 -1278 +1265 5 10 -1245 +1233 10 43 -1179 +1167 44 218 -804 +795 @@ -19307,19 +19297,19 @@ membervariables -329658 +325582 id -325099 +321201 type_id -145086 +139772 name -59068 +56776 @@ -19333,12 +19323,12 @@ 1 2 -320637 +316912 2 7 -4461 +4288 @@ -19354,7 +19344,7 @@ 1 2 -325099 +321201 @@ -19370,22 +19360,22 @@ 1 2 -118391 +113949 2 3 -13396 +12934 3 11 -10989 +10656 11 -1212 -2309 +1715 +2231 @@ -19401,17 +19391,17 @@ 1 2 -125916 +121310 2 3 -9883 +9511 3 266 -9287 +8950 @@ -19427,32 +19417,32 @@ 1 2 -31217 +29971 2 3 -9056 +8705 3 4 -5944 +5725 4 6 -4485 +4311 6 15 -4534 +4358 15 -1317 -3829 +1953 +3704 @@ -19468,32 +19458,32 @@ 1 2 -38256 +36736 2 3 -7524 +7232 3 4 -4035 +3891 4 7 -4765 +4592 7 -319 -4437 +291 +4264 -323 +318 605 -48 +58 @@ -19674,19 +19664,19 @@ localvariables -527180 +521836 id -527101 +521758 type_id -48087 +47599 name -76217 +75444 @@ -19700,12 +19690,12 @@ 1 2 -527022 +521680 2 3 -79 +78 @@ -19721,7 +19711,7 @@ 1 2 -527101 +521758 @@ -19737,32 +19727,32 @@ 1 2 -26759 +26487 2 3 -6841 +6772 3 4 -2893 +2864 4 6 -4119 +4077 6 13 -3862 +3823 13 4908 -3611 +3575 @@ -19778,22 +19768,22 @@ 1 2 -36072 +35706 2 3 -4969 +4919 3 5 -4323 +4279 5 1158 -2722 +2694 @@ -19809,32 +19799,32 @@ 1 2 -43526 +43085 2 3 -13096 +12963 3 4 -5140 +5088 4 7 -6821 +6752 7 31 -5767 +5708 31 6112 -1865 +1846 @@ -19850,17 +19840,17 @@ 1 2 -64564 +63910 2 3 -6472 +6406 3 819 -5180 +5127 @@ -19870,11 +19860,11 @@ autoderivation -19759 +19559 var -19759 +19559 derivation_type @@ -19892,7 +19882,7 @@ 1 2 -19759 +19559 @@ -19938,31 +19928,31 @@ enumconstants -94487 +94097 id -94487 +94097 parent -7539 +8031 index -7678 +7600 type_id -7394 +7887 name -73851 +73102 location -76856 +76077 @@ -19976,7 +19966,7 @@ 1 2 -94487 +94097 @@ -19992,7 +19982,7 @@ 1 2 -94487 +94097 @@ -20008,7 +19998,7 @@ 1 2 -94487 +94097 @@ -20024,7 +20014,7 @@ 1 2 -94487 +94097 @@ -20040,7 +20030,7 @@ 1 2 -94487 +94097 @@ -20056,47 +20046,47 @@ 1 2 -1041 +1598 2 3 -830 +822 3 4 -2484 +2459 4 5 -586 +580 5 6 -586 +580 6 -8 -540 +9 +730 -8 -13 -659 +9 +16 +613 -13 -46 -573 +16 +392 +606 -46 +426 1166 -237 +39 @@ -20112,47 +20102,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 +9 +704 -8 -13 -632 +9 +17 +626 -13 -49 -566 - - -50 +17 1166 -224 +600 @@ -20168,12 +20153,12 @@ 1 2 -6788 +7287 2 3 -751 +743 @@ -20189,47 +20174,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 +9 +704 -8 -13 -632 +9 +17 +626 -13 -49 -566 - - -50 +17 1166 -224 +600 @@ -20245,47 +20225,47 @@ 1 2 -1080 +1637 2 3 -843 +835 3 4 -2484 +2459 4 5 -586 +580 5 6 -566 +561 6 -8 -514 +9 +704 -8 -13 -659 +9 +16 +613 -13 -46 -566 +16 +427 +606 -46 +466 1166 -237 +32 @@ -20301,47 +20281,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 30 -606 +600 30 -1166 -355 +1253 +352 @@ -20357,47 +20337,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 29 -606 +600 29 -1145 -355 +1232 +352 @@ -20413,47 +20393,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 28 -606 +600 28 -1123 -355 +1210 +352 @@ -20469,47 +20449,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 674 -355 +352 @@ -20525,47 +20505,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 774 -355 +352 @@ -20581,47 +20561,47 @@ 1 2 -1041 +1598 2 3 -810 +802 3 4 -2458 +2433 4 5 -566 +561 5 6 -566 +561 6 -8 -520 +9 +704 -8 -13 -639 +9 +16 +600 -13 -46 -560 +16 +470 +593 -46 +479 1166 -230 +32 @@ -20637,7 +20617,7 @@ 1 2 -7388 +7881 137 @@ -20658,47 +20638,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 +9 +678 -8 -13 -612 +9 +17 +613 -13 -51 -560 - - -52 +17 1166 -210 +580 @@ -20714,47 +20689,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 +9 +678 -8 -13 -612 +9 +17 +613 -13 -51 -560 - - -52 +17 1166 -210 +580 @@ -20770,47 +20740,47 @@ 1 2 -1080 +1637 2 3 -823 +815 3 4 -2458 +2433 4 5 -566 +561 5 6 -547 +541 6 -8 -494 +9 +678 -8 -13 -639 +9 +16 +600 -13 -47 -560 +16 +470 +593 -48 +621 1166 -224 +26 @@ -20826,17 +20796,17 @@ 1 2 -66396 +65723 2 3 -6927 +6856 3 239 -527 +521 @@ -20852,17 +20822,17 @@ 1 2 -67049 +66369 2 3 -6274 +6210 3 239 -527 +521 @@ -20878,12 +20848,12 @@ 1 2 -68762 +68065 2 13 -5088 +5036 @@ -20899,17 +20869,17 @@ 1 2 -61941 +61313 2 3 -11382 +11267 3 239 -527 +521 @@ -20925,12 +20895,12 @@ 1 2 -71346 +70623 2 23 -2504 +2479 @@ -20946,12 +20916,12 @@ 1 2 -71531 +70773 2 229 -5325 +5304 @@ -20967,12 +20937,12 @@ 1 2 -71643 +70884 2 229 -5213 +5193 @@ -20988,12 +20958,12 @@ 1 2 -73211 +72469 2 17 -3644 +3607 @@ -21009,17 +20979,17 @@ 1 2 -66535 +65828 2 3 -10090 +9994 3 229 -230 +254 @@ -21035,12 +21005,12 @@ 1 2 -76685 +75907 2 27 -171 +169 @@ -21050,31 +21020,31 @@ builtintypes -559 +537 id -559 +537 name -559 +537 kind -559 +537 size -85 +81 sign -36 +35 alignment -60 +58 @@ -21088,7 +21058,7 @@ 1 2 -559 +537 @@ -21104,7 +21074,7 @@ 1 2 -559 +537 @@ -21120,7 +21090,7 @@ 1 2 -559 +537 @@ -21136,7 +21106,7 @@ 1 2 -559 +537 @@ -21152,7 +21122,7 @@ 1 2 -559 +537 @@ -21168,7 +21138,7 @@ 1 2 -559 +537 @@ -21184,7 +21154,7 @@ 1 2 -559 +537 @@ -21200,7 +21170,7 @@ 1 2 -559 +537 @@ -21216,7 +21186,7 @@ 1 2 -559 +537 @@ -21232,7 +21202,7 @@ 1 2 -559 +537 @@ -21248,7 +21218,7 @@ 1 2 -559 +537 @@ -21264,7 +21234,7 @@ 1 2 -559 +537 @@ -21280,7 +21250,7 @@ 1 2 -559 +537 @@ -21296,7 +21266,7 @@ 1 2 -559 +537 @@ -21312,7 +21282,7 @@ 1 2 -559 +537 @@ -21328,37 +21298,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21374,37 +21344,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21420,37 +21390,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21466,12 +21436,12 @@ 1 2 -24 +23 3 4 -60 +58 @@ -21487,12 +21457,12 @@ 1 2 -60 +58 2 3 -24 +23 @@ -21508,17 +21478,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21534,17 +21504,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21560,17 +21530,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21586,12 +21556,12 @@ 5 6 -24 +23 7 8 -12 +11 @@ -21607,7 +21577,7 @@ 5 6 -36 +35 @@ -21623,27 +21593,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21659,27 +21629,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21695,27 +21665,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21731,12 +21701,12 @@ 1 2 -12 +11 2 3 -48 +46 @@ -21752,7 +21722,7 @@ 3 4 -60 +58 @@ -21762,23 +21732,23 @@ derivedtypes -4572495 +4651908 id -4572495 +4651908 name -2240442 +2328554 kind -97 +93 type_id -2743147 +2780308 @@ -21792,7 +21762,7 @@ 1 2 -4572495 +4651908 @@ -21808,7 +21778,7 @@ 1 2 -4572495 +4651908 @@ -21824,7 +21794,7 @@ 1 2 -4572495 +4651908 @@ -21840,17 +21810,17 @@ 1 2 -1640327 +1709696 2 3 -479376 +500222 3 -42612 -120737 +43371 +118634 @@ -21866,12 +21836,12 @@ 1 2 -2240417 +2328530 2 3 -24 +23 @@ -21887,17 +21857,17 @@ 1 2 -1640607 +1709965 2 3 -479097 +499954 3 -42594 -120737 +43353 +118634 @@ -21913,42 +21883,42 @@ 21 22 -12 +11 61 62 -12 +11 2051 2052 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97759 -97760 -12 +102765 +102766 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -21964,42 +21934,42 @@ 1 2 -12 +11 13 14 -12 +11 38 39 -12 +11 1152 1153 -12 +11 -13367 -13368 -12 +15027 +15028 +11 -36098 -36099 -12 +39331 +39332 +11 -50248 -50249 -12 +53789 +53790 +11 -83386 -83387 -12 +89933 +89934 +11 @@ -22015,42 +21985,42 @@ 12 13 -12 +11 21 22 -12 +11 969 970 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97431 -97432 -12 +102434 +102435 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -22066,22 +22036,22 @@ 1 2 -1661856 +1683160 2 3 -405550 +392781 3 4 -615674 +646083 4 202 -60064 +58283 @@ -22097,22 +22067,22 @@ 1 2 -1663206 +1684457 2 3 -405380 +392618 3 4 -614495 +644949 4 198 -60064 +58283 @@ -22128,22 +22098,22 @@ 1 2 -1663534 +1684784 2 3 -406814 +393985 3 4 -614446 +644902 4 7 -58350 +56635 @@ -22153,19 +22123,19 @@ pointerishsize -3358396 +3426426 id -3358396 +3426426 size -24 +23 alignment -12 +11 @@ -22179,7 +22149,7 @@ 1 2 -3358396 +3426426 @@ -22195,7 +22165,7 @@ 1 2 -3358396 +3426426 @@ -22211,12 +22181,12 @@ 21 22 -12 +11 -276244 -276245 -12 +293219 +293220 +11 @@ -22232,7 +22202,7 @@ 1 2 -24 +23 @@ -22246,9 +22216,9 @@ 12 -276265 -276266 -12 +293240 +293241 +11 @@ -22264,7 +22234,7 @@ 2 3 -12 +11 @@ -22274,23 +22244,23 @@ arraysizes -18830 +18099 id -18830 +18099 num_elements -2394 +2301 bytesize -2783 +2675 alignment -85 +81 @@ -22304,7 +22274,7 @@ 1 2 -18830 +18099 @@ -22320,7 +22290,7 @@ 1 2 -18830 +18099 @@ -22336,7 +22306,7 @@ 1 2 -18830 +18099 @@ -22352,37 +22322,37 @@ 1 2 -182 +175 2 3 -1422 +1367 3 4 -85 +81 4 5 -182 +175 5 13 -182 +175 13 25 -182 +175 38 116 -158 +151 @@ -22398,27 +22368,27 @@ 1 2 -1762 +1694 2 3 -243 +233 3 4 -133 +128 4 6 -182 +175 6 11 -72 +70 @@ -22434,27 +22404,27 @@ 1 2 -1774 +1705 2 3 -255 +245 3 4 -158 +151 4 7 -182 +175 7 8 -24 +23 @@ -22470,42 +22440,42 @@ 1 2 -170 +163 2 3 -1556 +1495 3 4 -133 +128 4 6 -218 +210 6 9 -218 +210 9 17 -218 +210 17 53 -218 +210 55 75 -48 +46 @@ -22521,22 +22491,22 @@ 1 2 -2115 +2033 2 3 -389 +373 3 6 -243 +233 6 7 -36 +35 @@ -22552,22 +22522,22 @@ 1 2 -2176 +2091 2 3 -303 +292 3 5 -255 +245 5 7 -48 +46 @@ -22583,37 +22553,37 @@ 17 18 -12 +11 18 19 -12 +11 33 34 -12 +11 50 51 -12 +11 181 182 -12 +11 389 390 -12 +11 861 862 -12 +11 @@ -22629,37 +22599,37 @@ 4 5 -12 +11 5 6 -12 +11 13 14 -12 +11 16 17 -12 +11 39 40 -12 +11 40 41 -12 +11 190 191 -12 +11 @@ -22675,37 +22645,37 @@ 1 2 -12 +11 2 3 -12 +11 14 15 -12 +11 17 18 -12 +11 41 42 -12 +11 53 54 -12 +11 191 192 -12 +11 @@ -22715,15 +22685,15 @@ typedefbase -1919913 +1867884 id -1919913 +1867884 type_id -899600 +871937 @@ -22737,7 +22707,7 @@ 1 2 -1919913 +1867884 @@ -22753,22 +22723,22 @@ 1 2 -698168 +676919 2 3 -93312 +90264 3 6 -72975 +70856 6 -5423 -35144 +5485 +33897 @@ -22778,23 +22748,23 @@ decltypes -45841 +44063 id -45841 +44063 expr -43325 +41644 base_type -6479 +6227 parentheses_would_change_meaning -24 +23 @@ -22808,7 +22778,7 @@ 1 2 -45841 +44063 @@ -22824,7 +22794,7 @@ 1 2 -45841 +44063 @@ -22840,7 +22810,7 @@ 1 2 -45841 +44063 @@ -22856,12 +22826,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22877,12 +22847,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22898,7 +22868,7 @@ 1 2 -43325 +41644 @@ -22914,17 +22884,17 @@ 1 2 -3622 +3482 2 3 -2552 +2453 3 277 -303 +292 @@ -22940,22 +22910,22 @@ 1 2 -2540 +2442 2 3 -3282 +3154 3 12 -522 +502 13 2445 -133 +128 @@ -22971,7 +22941,7 @@ 1 2 -6479 +6227 @@ -22987,12 +22957,12 @@ 8 9 -12 +11 1082 1083 -12 +11 @@ -23008,12 +22978,12 @@ 8 9 -12 +11 3556 3557 -12 +11 @@ -23029,12 +22999,12 @@ 8 9 -12 +11 525 526 -12 +11 @@ -23044,19 +23014,19 @@ usertypes -4363319 +4337028 id -4363319 +4337028 name -899429 +917472 kind -133 +128 @@ -23070,7 +23040,7 @@ 1 2 -4363319 +4337028 @@ -23086,7 +23056,7 @@ 1 2 -4363319 +4337028 @@ -23102,22 +23072,22 @@ 1 2 -596127 +606962 2 3 -199888 +203676 3 8 -67589 +69886 8 -31201 -35824 +32070 +36947 @@ -23133,12 +23103,12 @@ 1 2 -842355 +861619 2 10 -57074 +55852 @@ -23154,57 +23124,57 @@ 23 24 -12 +11 372 373 -12 +11 773 774 -12 +11 -1526 -1527 -12 +1856 +1857 +11 -4123 -4124 -12 +4195 +4196 +11 14604 14605 -12 +11 -17528 -17529 -12 +17544 +17545 +11 -20287 -20288 -12 +20425 +20426 +11 -75247 -75248 -12 +75551 +75552 +11 -81118 -81119 -12 +90575 +90576 +11 -143330 -143331 -12 +145253 +145254 +11 @@ -23220,52 +23190,52 @@ 16 17 -12 +11 38 39 -24 +23 404 405 -12 +11 548 549 -12 +11 -776 -777 -12 +777 +778 +11 -2846 -2847 -12 +2848 +2849 +11 4545 4546 -12 +11 -9121 -9122 -12 +9129 +9130 +11 11659 11660 -12 +11 -49218 -49219 -12 +53824 +53825 +11 @@ -23275,19 +23245,19 @@ usertypesize -1364814 +1420908 id -1364814 +1420908 size -1641 +1577 alignment -97 +93 @@ -23301,7 +23271,7 @@ 1 2 -1364814 +1420908 @@ -23317,7 +23287,7 @@ 1 2 -1364814 +1420908 @@ -23333,52 +23303,52 @@ 1 2 -474 +455 2 3 -218 +210 3 4 -72 +70 4 5 -109 +105 5 8 -121 +116 8 12 -109 +105 12 16 -133 +128 16 36 -133 +128 37 170 -133 +128 260 -86086 -133 +95028 +128 @@ -23394,17 +23364,17 @@ 1 2 -1349 +1297 2 3 -194 +186 3 6 -97 +93 @@ -23420,42 +23390,42 @@ 1 2 -12 +11 3 4 -12 +11 7 8 -12 +11 50 51 -12 +11 54 55 -12 +11 -1916 -1917 -12 +2246 +2247 +11 -9656 -9657 -12 +9717 +9718 +11 -100584 -100585 -12 +109526 +109527 +11 @@ -23471,37 +23441,37 @@ 1 2 -24 +23 3 4 -12 +11 8 9 -12 +11 12 13 -12 +11 17 18 -12 +11 25 26 -12 +11 106 107 -12 +11 @@ -23511,26 +23481,26 @@ usertype_final -1331 +1317 id -1331 +1317 usertype_uuid -4897 +4847 id -4897 +4847 uuid -4897 +4847 @@ -23544,7 +23514,7 @@ 1 2 -4897 +4847 @@ -23560,7 +23530,7 @@ 1 2 -4897 +4847 @@ -23570,15 +23540,15 @@ mangled_name -4359684 +4333558 id -4359684 +4333558 mangled_name -532986 +514256 @@ -23592,7 +23562,7 @@ 1 2 -4359684 +4333558 @@ -23608,32 +23578,32 @@ 1 2 -325269 +310895 2 3 -68246 +66497 3 4 -35958 +35217 4 -8 -45307 +7 +39225 -8 -34 -40237 +7 +23 +38664 -34 -8470 -17967 +23 +8589 +23755 @@ -23643,59 +23613,59 @@ is_pod_class -1041477 +1104649 id -1041477 +1104649 is_standard_layout_class -1118962 +1180366 id -1118962 +1180366 is_complete -1345984 +1398952 id -1345984 +1398952 is_class_template -246617 +238660 id -246617 +238660 class_instantiation -1108921 +1176522 to -1107195 +1174863 from -72513 +72363 @@ -23709,12 +23679,12 @@ 1 2 -1105566 +1173297 2 4 -1628 +1565 @@ -23730,47 +23700,47 @@ 1 2 -21601 +21289 2 3 -12897 +12771 3 4 -7488 +7314 4 5 -4789 +4942 5 7 -5871 +5994 7 11 -6503 +6438 11 20 -5555 +5585 20 -89 -5470 +87 +5456 -89 -2079 -2334 +87 +3629 +2570 @@ -23780,19 +23750,19 @@ class_template_argument -2800063 +3135757 type_id -1339675 +1428725 index -1361 +1308 arg_type -921287 +904899 @@ -23806,27 +23776,27 @@ 1 2 -593732 +586000 2 3 -438105 +428957 3 4 -175599 +258501 4 7 -108629 +129501 7 113 -23607 +25764 @@ -23842,22 +23812,22 @@ 1 2 -619710 +613658 2 3 -445691 +442173 3 4 -187999 +272382 4 113 -86274 +100511 @@ -23873,37 +23843,37 @@ 1 2 -12 +11 2 3 -863 +829 3 26 -109 +105 29 64 -109 +105 69 -427 -109 +435 +105 -594 -8438 -109 +616 +9263 +105 -11951 -101100 -48 +13601 +119714 +46 @@ -23919,37 +23889,37 @@ 1 2 -12 +11 2 3 -863 +829 3 14 -121 +116 14 26 -109 +105 29 -147 -109 +148 +105 -191 -3560 -109 +198 +3591 +105 -11321 -39550 -36 +11582 +41130 +35 @@ -23965,22 +23935,27 @@ 1 2 -571096 +550198 2 3 -205784 +200100 3 -5 -75369 +4 +54918 -5 -5259 -69036 +4 +10 +70727 + + +10 +11421 +28954 @@ -23996,17 +23971,253 @@ 1 2 -805922 +786767 2 3 -96011 +98069 3 22 -19353 +20062 + + + + + + + + +class_template_argument_value +362635 + + +type_id +233565 + + +index +163 + + +arg_value +345447 + + + + +type_id +index + + +12 + + +1 +2 +209845 + + +2 +3 +14512 + + +3 +14 +9207 + + + + + + +type_id +arg_value + + +12 + + +1 +2 +197436 + + +2 +3 +17971 + + +3 +22 +17527 + + +24 +173 +630 + + + + + + +index +type_id + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +25 +26 +11 + + +206 +207 +11 + + +389 +390 +11 + + +552 +553 +11 + + +1312 +1313 +11 + + +5393 +5394 +11 + + +5423 +5424 +11 + + +9668 +9669 +11 + + + + + + +index +arg_value + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +42 +43 +11 + + +311 +312 +11 + + +514 +515 +11 + + +715 +716 +11 + + +1585 +1586 +11 + + +6302 +6303 +11 + + +8160 +8161 +11 + + +11875 +11876 +11 + + + + + + +arg_value +type_id + + +12 + + +1 +2 +328387 + + +2 +4 +17059 + + + + + + +arg_value +index + + +12 + + +1 +2 +345447 @@ -24016,15 +24227,15 @@ is_proxy_class_for -50120 +49017 id -50120 +49017 templ_param_id -50120 +49017 @@ -24038,7 +24249,7 @@ 1 2 -50120 +49017 @@ -24054,7 +24265,7 @@ 1 2 -50120 +49017 @@ -24064,19 +24275,19 @@ type_mentions -1699359 +1682135 id -1699359 +1682135 type_id -68077 +67387 location -1668455 +1651543 kind @@ -24094,7 +24305,7 @@ 1 2 -1699359 +1682135 @@ -24110,7 +24321,7 @@ 1 2 -1699359 +1682135 @@ -24126,7 +24337,7 @@ 1 2 -1699359 +1682135 @@ -24142,37 +24353,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24188,37 +24399,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24234,12 +24445,12 @@ 1 2 -66818 +66141 2 3 -1258 +1246 @@ -24255,12 +24466,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24276,12 +24487,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24297,7 +24508,7 @@ 1 2 -1668455 +1651543 @@ -24370,26 +24581,26 @@ is_function_template -1058083 +1023581 id -1058083 +1023581 function_instantiation -739463 +719194 to -739463 +719194 from -136103 +134923 @@ -24403,7 +24614,7 @@ 1 2 -739463 +719194 @@ -24419,37 +24630,32 @@ 1 2 -63018 +64125 2 3 -32396 +31385 3 4 -8193 +7898 4 -5 -9299 +6 +12467 -5 -10 -10940 +6 +15 +10434 -10 -57 -10223 - - -58 +15 645 -2030 +8611 @@ -24459,19 +24665,19 @@ function_template_argument -1910796 +1981225 function_id -1112422 +1088560 index -243 +233 arg_type -369847 +359386 @@ -24485,22 +24691,22 @@ 1 2 -634796 +600045 2 3 -361033 +302330 3 -5 -84645 +4 +131242 -5 +4 21 -31947 +54941 @@ -24516,22 +24722,22 @@ 1 2 -657966 +618530 2 3 -332393 +293520 3 -5 -90905 +4 +116683 -5 +4 21 -31156 +59825 @@ -24547,102 +24753,102 @@ 4 5 -12 +11 7 8 -12 +11 17 18 -12 +11 39 40 -12 +11 65 66 -12 +11 152 153 -12 +11 -238 -239 -12 +241 +242 +11 -325 -326 -12 +328 +329 +11 -422 -423 -12 +425 +426 +11 -520 -521 -12 +523 +524 +11 -754 -755 -12 +758 +759 +11 -1007 -1008 -12 +1011 +1012 +11 -1259 -1260 -12 +1520 +1521 +11 -1514 -1515 -12 +1701 +1702 +11 -2559 -2560 -12 +2566 +2567 +11 -2804 -2805 -12 +2917 +2918 +11 -4818 -4819 -12 +5686 +5687 +11 -13309 -13310 -12 +17602 +17603 +11 -40569 -40570 -12 +42858 +42859 +11 -84931 -84932 -12 +88286 +88287 +11 @@ -24658,102 +24864,102 @@ 4 5 -12 +11 7 8 -12 +11 14 15 -12 +11 22 23 -12 +11 32 33 -12 +11 54 55 -12 +11 -57 -58 -12 +60 +61 +11 -61 -62 -12 +62 +63 +11 -75 -76 -12 +78 +79 +11 -90 -91 -12 +91 +92 +11 -137 -138 -12 +140 +141 +11 214 215 -12 +11 -238 -239 -12 +242 +243 +11 -316 -317 -12 +317 +318 +11 -517 -518 -12 +521 +522 +11 -695 -696 -12 +700 +701 +11 -1468 -1469 -12 +1491 +1492 +11 -3652 -3653 -12 +3698 +3699 +11 -8773 -8774 -12 +8798 +8799 +11 -17388 -17389 -12 +17653 +17654 +11 @@ -24769,27 +24975,27 @@ 1 2 -249547 +242738 2 3 -48698 +46902 3 6 -29783 +28756 6 -19 -27996 +20 +27704 -19 -906 -13821 +20 +1989 +13285 @@ -24805,17 +25011,238 @@ 1 2 -341230 +331740 2 5 -28129 +27131 5 -10 -486 +12 +514 + + + + + + + + +function_template_argument_value +209892 + + +function_id +113037 + + +index +163 + + +arg_value +181755 + + + + +function_id +index + + +12 + + +1 +2 +107207 + + +2 +14 +5830 + + + + + + +function_id +arg_value + + +12 + + +1 +2 +89610 + + +2 +3 +17106 + + +3 +113 +6321 + + + + + + +index +function_id + + +12 + + +3 +4 +70 + + +5 +6 +11 + + +6 +7 +11 + + +111 +112 +11 + + +441 +442 +11 + + +857 +858 +11 + + +2136 +2137 +11 + + +2428 +2429 +11 + + +4217 +4218 +11 + + + + + + +index +arg_value + + +12 + + +5 +6 +70 + + +7 +8 +11 + + +8 +9 +11 + + +157 +158 +11 + + +405 +406 +11 + + +973 +974 +11 + + +2523 +2524 +11 + + +4848 +4849 +11 + + +6604 +6605 +11 + + + + + + +arg_value +function_id + + +12 + + +1 +2 +153712 + + +2 +3 +27949 + + +3 +4 +93 + + + + + + +arg_value +index + + +12 + + +1 +2 +181755 @@ -24825,26 +25252,26 @@ is_variable_template -19778 +19011 id -19778 +19011 variable_instantiation -31837 +38057 to -31837 +38057 from -6734 +6929 @@ -24858,7 +25285,7 @@ 1 2 -31837 +38057 @@ -24874,37 +25301,37 @@ 1 2 -2382 +2383 2 3 -2030 +2033 3 4 -449 +432 4 5 -692 +782 5 9 -534 +560 9 -29 -534 +21 +525 -42 -214 -109 +24 +286 +210 @@ -24914,11 +25341,11 @@ variable_template_argument -5529 +5499 variable_id -843 +848 index @@ -24926,7 +25353,7 @@ arg_type -4257 +4214 @@ -24940,12 +25367,12 @@ 1 2 -692 +685 2 3 -112 +123 3 @@ -24966,12 +25393,12 @@ 1 2 -369 +371 2 3 -125 +130 3 @@ -24981,12 +25408,12 @@ 4 6 -72 +71 6 8 -72 +71 8 @@ -25025,13 +25452,13 @@ 6 -9 -10 +10 +11 6 -17 -18 +20 +21 6 @@ -25066,8 +25493,8 @@ 6 -137 -138 +139 +140 6 @@ -25089,17 +25516,17 @@ 1 2 -3532 +3490 2 3 -481 +476 3 11 -243 +247 @@ -25115,12 +25542,148 @@ 1 2 -4046 +3999 + + +2 +4 +215 + + + + + + + + +variable_template_argument_value +137 + + +variable_id +19 + + +index +13 + + +arg_value +137 + + + + +variable_id +index + + +12 + + +1 +2 +13 2 3 -210 +6 + + + + + + +variable_id +arg_value + + +12 + + +3 +4 +13 + + +15 +16 +6 + + + + + + +index +variable_id + + +12 + + +1 +2 +6 + + +3 +4 +6 + + + + + + +index +arg_value + + +12 + + +6 +7 +6 + + +15 +16 +6 + + + + + + +arg_value +variable_id + + +12 + + +1 +2 +137 + + + + + + +arg_value +index + + +12 + + +1 +2 +137 @@ -25130,15 +25693,15 @@ routinetypes -444572 +436132 id -444572 +436132 return_type -184814 +178086 @@ -25152,7 +25715,7 @@ 1 2 -444572 +436132 @@ -25168,22 +25731,22 @@ 1 2 -148344 +142985 2 3 -21030 +20191 3 -18 -13943 +17 +13367 -18 -7709 -1495 +17 +8001 +1542 @@ -25193,19 +25756,19 @@ routinetypeargs -741201 +726544 routine -362760 +357377 index -389 +373 type_id -209394 +208724 @@ -25219,27 +25782,27 @@ 1 2 -169412 +166448 2 3 -95355 +96574 3 4 -58144 +55888 4 6 -31351 +30298 6 33 -8497 +8167 @@ -25255,22 +25818,22 @@ 1 2 -194831 +190916 2 3 -95853 +97018 3 4 -49707 +47778 4 22 -22367 +21663 @@ -25286,62 +25849,62 @@ 1 2 -133 +128 2 7 -24 +23 10 16 -24 +23 19 33 -24 +23 52 74 -24 +23 93 115 -24 +23 139 199 -24 +23 269 364 -24 +23 473 700 -24 +23 1319 -3279 -24 +3293 +23 -8061 -15906 -24 +8075 +16341 +23 -29841 -29842 -12 +30585 +30586 +11 @@ -25357,62 +25920,62 @@ 1 2 -133 +128 2 5 -24 +23 6 10 -24 +23 11 22 -24 +23 33 37 -24 +23 38 42 -24 +23 44 83 -24 +23 124 183 -24 +23 248 346 -24 +23 463 950 -24 +23 -2463 -5546 -24 +2464 +5642 +23 -12306 -12307 -12 +12850 +12851 +11 @@ -25428,27 +25991,27 @@ 1 2 -123691 +124231 2 3 -40869 +41258 3 4 -13505 +13016 4 7 -17942 +17293 7 -1097 -13384 +1099 +12923 @@ -25464,17 +26027,17 @@ 1 2 -156830 +158176 2 3 -41161 +39576 3 33 -11402 +10971 @@ -25484,19 +26047,19 @@ ptrtomembers -12180 +13227 id -12180 +13227 type_id -10247 +10013 class_id -5519 +6601 @@ -25510,7 +26073,7 @@ 1 2 -12180 +13227 @@ -25526,7 +26089,7 @@ 1 2 -12180 +13227 @@ -25542,12 +26105,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25563,12 +26126,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25584,22 +26147,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25615,22 +26178,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25640,15 +26203,15 @@ specifiers -547 +525 id -547 +525 str -547 +525 @@ -25662,7 +26225,7 @@ 1 2 -547 +525 @@ -25678,7 +26241,7 @@ 1 2 -547 +525 @@ -25688,15 +26251,15 @@ typespecifiers -1464874 +1479986 type_id -1460193 +1472695 spec_id -85 +81 @@ -25710,12 +26273,12 @@ 1 2 -1455513 +1465403 2 3 -4680 +7291 @@ -25731,37 +26294,37 @@ 102 103 -12 +11 222 223 -12 +11 518 519 -12 +11 -718 -719 -12 +957 +958 +11 2323 2324 -12 +11 -19328 -19329 -12 +20241 +20242 +11 -97291 -97292 -12 +102297 +102298 +11 @@ -25771,15 +26334,15 @@ funspecifiers -11370456 +11412148 func_id -3511992 +3500391 spec_id -194 +186 @@ -25793,27 +26356,27 @@ 1 2 -342616 +329999 2 3 -464083 +448167 3 4 -909155 +883458 4 5 -1670402 +1717910 5 8 -125733 +120855 @@ -25829,82 +26392,82 @@ 22 23 -12 +11 169 170 -12 +11 491 492 -12 +11 -506 -507 -12 +598 +599 +11 632 633 -12 +11 5650 5651 -12 +11 9530 9531 -12 +11 10451 10452 -12 +11 -11821 -11822 -12 +11834 +11835 +11 14848 14849 -12 +11 -25330 -25331 -12 +26196 +26197 +11 -33532 -33533 -12 +33724 +33725 +11 -122462 -122463 -12 +131801 +131802 +11 -204591 -204592 -12 +214925 +214926 +11 -232301 -232302 -12 +242884 +242885 +11 -263009 -263010 -12 +272918 +272919 +11 @@ -25914,11 +26477,11 @@ varspecifiers -1124158 +1113938 var_id -935091 +926194 spec_id @@ -25936,17 +26499,17 @@ 1 2 -795258 +787198 2 3 -92279 +91911 3 5 -47553 +47084 @@ -25980,13 +26543,13 @@ 6 -8409 -8410 +8411 +8412 6 -8751 -8752 +8753 +8754 6 @@ -25995,13 +26558,13 @@ 6 -13352 -13353 +13439 +13440 6 -42323 -42324 +42412 +42413 6 @@ -26590,11 +27153,11 @@ attribute_args -118319 +118389 id -118319 +118389 kind @@ -26602,7 +27165,7 @@ attribute -116952 +117020 index @@ -26610,7 +27173,7 @@ location -58256 +58290 @@ -26624,7 +27187,7 @@ 1 2 -118319 +118389 @@ -26640,7 +27203,7 @@ 1 2 -118319 +118389 @@ -26656,7 +27219,7 @@ 1 2 -118319 +118389 @@ -26672,7 +27235,7 @@ 1 2 -118319 +118389 @@ -26772,12 +27335,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26793,7 +27356,7 @@ 1 2 -116431 +116499 2 @@ -26814,12 +27377,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26835,7 +27398,7 @@ 1 2 -116137 +116205 2 @@ -26955,22 +27518,22 @@ 1 2 -28468 +28485 2 3 -7516 +7521 3 4 -19458 +19469 4 25 -2812 +2814 @@ -26986,12 +27549,12 @@ 1 2 -52020 +52051 2 3 -6235 +6239 @@ -27007,22 +27570,22 @@ 1 2 -28452 +28469 2 3 -7534 +7539 3 4 -19454 +19466 4 25 -2814 +2815 @@ -27038,7 +27601,7 @@ 1 2 -58250 +58285 3 @@ -27053,15 +27616,15 @@ attribute_arg_value -118292 +118362 arg -118292 +118362 value -2257 +2258 @@ -27075,7 +27638,7 @@ 1 2 -118292 +118362 @@ -27091,7 +27654,7 @@ 1 2 -1808 +1809 2 @@ -27116,15 +27679,15 @@ attribute_arg_type -60 +58 arg -60 +58 type_id -36 +35 @@ -27138,7 +27701,7 @@ 1 2 -60 +58 @@ -27154,12 +27717,12 @@ 1 2 -12 +11 2 3 -24 +23 @@ -27222,15 +27785,15 @@ typeattributes -12119 +12701 type_id -10831 +11462 spec_id -12119 +12701 @@ -27244,12 +27807,12 @@ 1 2 -10296 +10948 2 34 -534 +514 @@ -27265,7 +27828,7 @@ 1 2 -12119 +12701 @@ -27275,15 +27838,15 @@ funcattributes -327044 +314529 func_id -174943 +168330 spec_id -327044 +314529 @@ -27297,22 +27860,22 @@ 1 2 -94078 +90603 2 3 -13554 +13028 3 4 -65134 +62606 4 14 -2176 +2091 @@ -27328,7 +27891,7 @@ 1 2 -327044 +314529 @@ -27444,15 +28007,15 @@ unspecifiedtype -9406353 +9451546 type_id -9406353 +9451546 unspecified_type_id -5062897 +5133540 @@ -27466,7 +28029,7 @@ 1 2 -9406353 +9451546 @@ -27482,22 +28045,17 @@ 1 2 -2733810 +2776289 2 3 -1943594 +1978655 3 -30 -379779 - - -30 -7873 -5713 +7936 +378596 @@ -27507,19 +28065,19 @@ member -5112192 +5066844 parent -809800 +833190 index -2966 +2851 child -5095258 +5050544 @@ -27533,47 +28091,47 @@ 1 2 -46948 +45126 2 3 -191658 +219789 3 4 -208336 +209109 4 5 -90285 +90638 5 7 -65073 +67210 7 9 -67212 +65539 9 15 -68221 +66497 15 -39 -62471 +45 +62758 -39 +45 245 -9591 +6520 @@ -27589,47 +28147,47 @@ 1 2 -46218 +44425 2 3 -191719 +219824 3 4 -202769 +203723 4 5 -93154 +93454 5 7 -65766 +67876 7 9 -67346 +65668 9 15 -68999 +67245 15 -38 -61462 +41 +62641 -38 +41 281 -12363 +8331 @@ -27645,62 +28203,62 @@ 1 2 -547 +525 2 5 -267 +257 5 9 -255 +245 9 18 -230 +222 23 100 -230 +222 122 186 -230 +222 188 293 -230 +222 296 374 -230 +222 375 542 -230 +222 572 3257 -230 +222 3427 -21556 -230 +22111 +222 -29162 -65993 -48 +30337 +70680 +46 @@ -27716,62 +28274,62 @@ 1 2 -534 +514 2 5 -218 +210 5 7 -230 +222 7 13 -230 +222 13 70 -230 +222 71 160 -230 +222 160 256 -230 +222 263 345 -230 +222 346 476 -243 +233 492 1685 -230 +222 1926 -8765 -230 +8775 +222 -10213 -66838 -121 +10226 +71530 +116 @@ -27787,7 +28345,7 @@ 1 2 -5095258 +5050544 @@ -27803,12 +28361,12 @@ 1 2 -5078555 +5034466 2 7 -16702 +16078 @@ -27818,15 +28376,15 @@ enclosingfunction -131751 +127164 child -131751 +127164 parent -74239 +71639 @@ -27840,7 +28398,7 @@ 1 2 -131751 +127164 @@ -27856,27 +28414,27 @@ 1 2 -39240 +37811 2 3 -21930 +21231 3 4 -7208 +6952 4 6 -5652 +5445 6 45 -206 +198 @@ -27886,27 +28444,27 @@ derivations -370309 +392220 derivation -370309 +392220 sub -346555 +367484 index -72 +70 super -237840 +236475 location -96351 +92613 @@ -27920,7 +28478,7 @@ 1 2 -370309 +392220 @@ -27936,7 +28494,7 @@ 1 2 -370309 +392220 @@ -27952,7 +28510,7 @@ 1 2 -370309 +392220 @@ -27968,7 +28526,7 @@ 1 2 -370309 +392220 @@ -27984,12 +28542,12 @@ 1 2 -326108 +345926 2 7 -20447 +21558 @@ -28005,12 +28563,12 @@ 1 2 -334933 +356161 2 7 -11621 +11322 @@ -28026,12 +28584,12 @@ 1 2 -326120 +345937 2 7 -20434 +21546 @@ -28047,12 +28605,12 @@ 1 2 -334921 +356150 2 7 -11633 +11334 @@ -28068,32 +28626,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -957 -958 -12 +970 +971 +11 -29236 -29237 -12 +32328 +32329 +11 @@ -28109,32 +28667,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -956 -957 -12 +969 +970 +11 -28508 -28509 -12 +31450 +31451 +11 @@ -28150,32 +28708,32 @@ 1 2 -12 +11 3 4 -12 +11 29 30 -12 +11 84 85 -12 +11 -441 -442 -12 +452 +453 +11 -19051 -19052 -12 +19713 +19714 +11 @@ -28191,32 +28749,32 @@ 1 2 -12 +11 4 5 -12 +11 17 18 -12 +11 51 52 -12 +11 254 255 -12 +11 7602 7603 -12 +11 @@ -28232,12 +28790,12 @@ 1 2 -222438 +221343 2 -766 -15402 +1134 +15131 @@ -28253,12 +28811,12 @@ 1 2 -222450 +221355 2 -766 -15390 +1134 +15120 @@ -28274,12 +28832,12 @@ 1 2 -237342 +235996 2 4 -498 +479 @@ -28295,12 +28853,12 @@ 1 2 -229780 +228634 2 439 -8059 +7840 @@ -28316,22 +28874,22 @@ 1 2 -74652 +70786 2 3 -9336 +8985 3 8 -7306 +7606 8 -682 -5057 +698 +5234 @@ -28347,22 +28905,22 @@ 1 2 -77193 +73146 2 3 -7002 +6858 3 -9 -7609 +8 +7443 -9 -682 -4546 +8 +698 +5164 @@ -28378,12 +28936,12 @@ 1 2 -96327 +92589 2 4 -24 +23 @@ -28399,22 +28957,22 @@ 1 2 -77655 +73882 2 3 -9056 +8833 3 -11 -7269 +10 +7326 -11 -682 -2370 +10 +698 +2570 @@ -28424,15 +28982,15 @@ derspecifiers -372947 +394756 der_id -370272 +392185 spec_id -48 +46 @@ -28446,12 +29004,12 @@ 1 2 -367598 +389615 2 3 -2674 +2570 @@ -28467,22 +29025,22 @@ 220 221 -12 +11 242 243 -12 +11 979 980 -12 +11 -29238 -29239 -12 +32343 +32344 +11 @@ -28492,15 +29050,15 @@ direct_base_offsets -282029 +307366 der_id -282029 +307366 offset -206 +210 @@ -28514,7 +29072,7 @@ 1 2 -282029 +307366 @@ -28530,62 +29088,67 @@ 1 2 -36 +46 2 3 -12 +11 4 5 -24 +23 5 6 -12 +11 6 7 -24 +11 7 8 -12 +23 8 9 -24 +11 + + +10 +11 +11 11 12 -12 +11 21 22 -12 +11 -78 -79 -12 +85 +86 +11 200 201 -12 +11 -22837 -22838 -12 +25931 +25932 +11 @@ -28595,19 +29158,19 @@ virtual_base_offsets -7026 +6753 sub -3890 +3739 super -534 +514 offset -267 +257 @@ -28621,22 +29184,22 @@ 1 2 -3063 +2944 2 4 -340 +327 4 7 -279 +268 7 11 -206 +198 @@ -28652,17 +29215,17 @@ 1 2 -3282 +3154 2 4 -328 +315 4 8 -279 +268 @@ -28678,52 +29241,52 @@ 1 2 -85 +81 2 3 -48 +46 3 4 -60 +58 4 5 -97 +93 5 7 -36 +35 8 13 -48 +46 13 15 -48 +46 15 23 -48 +46 24 60 -48 +46 196 197 -12 +11 @@ -28739,32 +29302,32 @@ 1 2 -303 +292 2 3 -85 +81 4 6 -36 +35 6 8 -48 +46 8 10 -48 +46 14 15 -12 +11 @@ -28780,57 +29343,57 @@ 2 3 -36 +35 4 5 -12 +11 5 6 -24 +23 6 8 -24 +23 8 9 -36 +35 10 12 -24 +23 14 19 -24 +23 20 27 -24 +23 28 31 -24 +23 36 97 -24 +23 97 98 -12 +11 @@ -28846,37 +29409,37 @@ 1 2 -85 +81 2 3 -36 +35 3 4 -48 +46 5 7 -24 +23 7 10 -24 +23 12 14 -24 +23 21 29 -24 +23 @@ -28886,23 +29449,23 @@ frienddecls -231178 +222208 id -231178 +222208 type_id -19511 +18753 decl_id -28810 +27692 location -8096 +7782 @@ -28916,7 +29479,7 @@ 1 2 -231178 +222208 @@ -28932,7 +29495,7 @@ 1 2 -231178 +222208 @@ -28948,7 +29511,7 @@ 1 2 -231178 +222208 @@ -28964,47 +29527,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29020,47 +29583,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29076,17 +29639,17 @@ 1 2 -17748 +17059 2 5 -1543 +1483 5 31 -218 +210 @@ -29102,37 +29665,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29148,37 +29711,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29194,12 +29757,12 @@ 1 2 -28215 +27120 2 46 -595 +572 @@ -29215,17 +29778,17 @@ 1 2 -6917 +6648 2 3 -1045 +1004 3 18239 -133 +128 @@ -29241,12 +29804,12 @@ 1 2 -7609 +7314 2 1215 -486 +467 @@ -29262,17 +29825,17 @@ 1 2 -6929 +6660 2 3 -1033 +993 3 1734 -133 +128 @@ -29282,19 +29845,19 @@ comments -1743633 +1675974 id -1743633 +1675974 contents -864492 +830947 location -1743633 +1675974 @@ -29308,7 +29871,7 @@ 1 2 -1743633 +1675974 @@ -29324,7 +29887,7 @@ 1 2 -1743633 +1675974 @@ -29340,17 +29903,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29366,17 +29929,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29392,7 +29955,7 @@ 1 2 -1743633 +1675974 @@ -29408,7 +29971,7 @@ 1 2 -1743633 +1675974 @@ -29418,15 +29981,15 @@ commentbinding -778436 +748230 id -679021 +652673 element -747438 +718434 @@ -29440,17 +30003,17 @@ 1 2 -616002 +592099 2 4 -58545 +56273 4 97 -4473 +4299 @@ -29466,12 +30029,12 @@ 1 2 -716439 +688638 2 3 -30998 +29796 @@ -29481,15 +30044,15 @@ exprconv -6445331 +6446816 converted -6445038 +6446523 conversion -6445331 +6446816 @@ -29503,7 +30066,7 @@ 1 2 -6444746 +6446231 2 @@ -29524,7 +30087,7 @@ 1 2 -6445331 +6446816 @@ -29534,30 +30097,30 @@ compgenerated -6720341 +6652484 id -6720341 +6652484 synthetic_destructor_call -59493 +57185 element -47422 +45582 i -340 +327 destructor_call -49573 +47650 @@ -29571,17 +30134,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29597,17 +30160,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29623,27 +30186,27 @@ 1 2 -255 +245 2 7 -24 +23 22 43 -24 +23 190 711 -24 +23 3901 3902 -12 +11 @@ -29659,27 +30222,27 @@ 1 2 -255 +245 2 7 -24 +23 21 37 -24 +23 146 550 -24 +23 3297 3298 -12 +11 @@ -29695,17 +30258,17 @@ 1 2 -43823 +42123 2 3 -3719 +3575 3 26 -2030 +1951 @@ -29721,7 +30284,7 @@ 1 2 -49573 +47650 @@ -29731,15 +30294,15 @@ namespaces -8497 +8167 id -8497 +8167 name -4570 +4393 @@ -29753,7 +30316,7 @@ 1 2 -8497 +8167 @@ -29769,17 +30332,17 @@ 1 2 -3841 +3692 2 3 -461 +444 3 139 -267 +257 @@ -29789,26 +30352,26 @@ namespace_inline -170 +163 id -170 +163 namespacembrs -1570027 +1616300 parentid -7913 +7606 memberid -1570027 +1616300 @@ -29822,62 +30385,67 @@ 1 2 -875 +829 2 3 -826 +794 3 4 -644 +385 4 -6 -680 - - -6 -9 +5 607 -9 -16 -680 +5 +8 +666 -16 -27 -607 +8 +14 +677 -27 -46 -619 - - -46 -85 -607 - - -85 -169 -607 - - -169 -444 +14 +22 595 -475 -29073 -559 +22 +42 +595 + + +42 +63 +572 + + +63 +127 +572 + + +127 +304 +572 + + +321 +1041 +572 + + +1101 +32701 +163 @@ -29893,7 +30461,7 @@ 1 2 -1570027 +1616300 @@ -29903,19 +30471,19 @@ exprparents -13615303 +13481241 expr_id -13615112 +13481052 child_index -3163 +3131 parent_id -9644209 +9549204 @@ -29929,7 +30497,7 @@ 1 2 -13615105 +13481045 2 @@ -29950,12 +30518,12 @@ 1 2 -13614927 +13480869 2 4 -184 +182 @@ -29971,37 +30539,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 46 -243 +241 46 56 -237 +234 56 3660 -237 +234 6434 -1187727 -46 +1188148 +45 @@ -30017,37 +30585,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 31 -243 +241 31 41 -237 +234 41 3645 -237 +234 6419 -1187740 -46 +1188161 +45 @@ -30063,17 +30631,17 @@ 1 2 -6840662 +6772879 2 3 -2212086 +2190858 3 1681 -591461 +585466 @@ -30089,17 +30657,17 @@ 1 2 -6840682 +6772898 2 3 -2212066 +2190839 3 480 -591461 +585466 @@ -30109,22 +30677,22 @@ expr_isload -5063114 +5014574 expr_id -5063114 +5014574 conversionkinds -4254113 +4255501 expr_id -4254113 +4255501 kind @@ -30142,7 +30710,7 @@ 1 2 -4254113 +4255501 @@ -30166,8 +30734,8 @@ 1 -13109 -13110 +13672 +13673 1 @@ -30181,8 +30749,8 @@ 1 -4161592 -4161593 +4162417 +4162418 1 @@ -30193,15 +30761,15 @@ iscall -2365240 +2284876 caller -2365240 +2284876 kind -36 +35 @@ -30215,7 +30783,7 @@ 1 2 -2365240 +2284876 @@ -30231,17 +30799,17 @@ 1319 1320 -12 +11 -5604 -5605 -12 +5643 +5644 +11 -187644 -187645 -12 +188582 +188583 +11 @@ -30251,15 +30819,15 @@ numtemplatearguments -157948 +152181 expr_id -157948 +152181 num -48 +46 @@ -30273,7 +30841,7 @@ 1 2 -157948 +152181 @@ -30289,22 +30857,22 @@ 3 4 -12 +11 41 42 -12 +11 651 652 -12 +11 -12298 -12299 -12 +12329 +12330 +11 @@ -30314,15 +30882,15 @@ specialnamequalifyingelements -12 +11 id -12 +11 name -12 +11 @@ -30336,7 +30904,7 @@ 1 2 -12 +11 @@ -30352,7 +30920,7 @@ 1 2 -12 +11 @@ -30362,23 +30930,23 @@ namequalifiers -1125621 +1116919 id -1125621 +1116919 qualifiableelement -1125621 +1116919 qualifyingelement -37001 +38961 location -509589 +506087 @@ -30392,7 +30960,7 @@ 1 2 -1125621 +1116919 @@ -30408,7 +30976,7 @@ 1 2 -1125621 +1116919 @@ -30424,7 +30992,7 @@ 1 2 -1125621 +1116919 @@ -30440,7 +31008,7 @@ 1 2 -1125621 +1116919 @@ -30456,7 +31024,7 @@ 1 2 -1125621 +1116919 @@ -30472,7 +31040,7 @@ 1 2 -1125621 +1116919 @@ -30488,109 +31056,109 @@ 1 2 -17109 +18965 2 3 -7935 +8142 3 4 -5081 - - -4 -10 -2860 - - -10 -86 -2781 - - -86 -24926 -1232 - - - - - - -qualifyingelement -qualifiableelement - - -12 - - -1 -2 -17109 - - -2 -3 -7935 - - -3 -4 -5081 - - -4 -10 -2860 - - -10 -86 -2781 - - -86 -24926 -1232 - - - - - - -qualifyingelement -location - - -12 - - -1 -2 -22745 - - -2 -3 -4817 - - -3 -4 -3802 +5043 4 11 -3018 +3027 + + +11 +129 +2935 + + +132 +24926 +848 + + + + + + +qualifyingelement +qualifiableelement + + +12 + + +1 +2 +18965 + + +2 +3 +8142 + + +3 +4 +5043 + + +4 +11 +3027 + + +11 +129 +2935 + + +132 +24926 +848 + + + + + + +qualifyingelement +location + + +12 + + +1 +2 +24850 + + +2 +3 +4762 + + +3 +4 +3770 + + +4 +11 +2974 11 16728 -2616 +2603 @@ -30606,22 +31174,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30637,22 +31205,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30668,17 +31236,17 @@ 1 2 -452478 +449080 2 3 -44785 +44650 3 190 -12324 +12356 @@ -30688,15 +31256,15 @@ varbind -5497554 +5445518 expr -5497428 +5445394 var -1549133 +1534266 @@ -30710,12 +31278,12 @@ 1 2 -5497303 +5445270 2 3 -125 +123 @@ -30731,32 +31299,32 @@ 1 2 -685882 +679661 2 3 -311295 +308179 3 4 -236831 +234430 4 5 -93953 +93020 5 9 -134777 +133430 9 6150 -86393 +85544 @@ -30766,15 +31334,15 @@ funbind -2442767 +2419854 expr -2142538 +2122577 fun -438611 +434205 @@ -30788,17 +31356,17 @@ 1 2 -1842553 +1825541 2 3 -299807 +296859 3 5 -177 +176 @@ -30814,32 +31382,32 @@ 1 2 -255153 +252065 2 3 -76151 +75516 3 4 -31642 +31302 4 7 -33910 +33957 7 37 -33831 +33520 37 6664 -7922 +7841 @@ -30849,19 +31417,19 @@ expr_allocator -27692 +26617 expr -27692 +26617 func -133 +128 form -12 +11 @@ -30875,7 +31443,7 @@ 1 2 -27692 +26617 @@ -30891,7 +31459,7 @@ 1 2 -27692 +26617 @@ -30907,42 +31475,42 @@ 1 2 -36 +35 3 4 -12 +11 4 5 -12 +11 5 6 -12 +11 7 8 -24 +23 39 40 -12 +11 973 974 -12 +11 1237 1238 -12 +11 @@ -30958,7 +31526,7 @@ 1 2 -133 +128 @@ -30974,7 +31542,7 @@ 2278 2279 -12 +11 @@ -30990,7 +31558,7 @@ 11 12 -12 +11 @@ -31000,19 +31568,19 @@ expr_deallocator -30998 +29796 expr -30998 +29796 func -145 +140 form -24 +23 @@ -31026,7 +31594,7 @@ 1 2 -30998 +29796 @@ -31042,7 +31610,7 @@ 1 2 -30998 +29796 @@ -31058,42 +31626,42 @@ 1 2 -36 +35 2 3 -24 +23 3 4 -12 +11 4 5 -12 +11 7 8 -24 +23 118 119 -12 +11 883 884 -12 +11 1521 1522 -12 +11 @@ -31109,7 +31677,7 @@ 1 2 -145 +140 @@ -31125,12 +31693,12 @@ 891 892 -12 +11 1659 1660 -12 +11 @@ -31146,12 +31714,12 @@ 4 5 -12 +11 8 9 -12 +11 @@ -31161,26 +31729,26 @@ expr_cond_two_operand -610 +611 cond -610 +611 expr_cond_guard -154429 +154519 cond -154429 +154519 guard -154429 +154519 @@ -31194,7 +31762,7 @@ 1 2 -154429 +154519 @@ -31210,7 +31778,7 @@ 1 2 -154429 +154519 @@ -31220,15 +31788,15 @@ expr_cond_true -154429 +154519 cond -154429 +154519 true -154429 +154519 @@ -31242,7 +31810,7 @@ 1 2 -154429 +154519 @@ -31258,7 +31826,7 @@ 1 2 -154429 +154519 @@ -31268,15 +31836,15 @@ expr_cond_false -154429 +154519 cond -154429 +154519 false -154429 +154519 @@ -31290,7 +31858,7 @@ 1 2 -154429 +154519 @@ -31306,7 +31874,7 @@ 1 2 -154429 +154519 @@ -31316,15 +31884,15 @@ values -8776796 +8788031 id -8776796 +8788031 str -651390 +651491 @@ -31338,7 +31906,7 @@ 1 2 -8776796 +8788031 @@ -31354,17 +31922,17 @@ 1 2 -540103 +540120 2 3 -65463 +65472 3 -4044535 -45824 +4046841 +45899 @@ -31374,15 +31942,15 @@ valuetext -4759381 +4766569 id -4759381 +4766569 text -704971 +705085 @@ -31396,7 +31964,7 @@ 1 2 -4759381 +4766569 @@ -31412,22 +31980,22 @@ 1 2 -528095 +528108 2 3 -102815 +102830 3 7 -56849 +56879 7 427516 -17212 +17268 @@ -31437,15 +32005,15 @@ valuebind -9499071 +9509366 val -8769631 +8779926 expr -9499071 +9509366 @@ -31459,7 +32027,7 @@ 1 2 -8040923 +8051218 2 @@ -31485,7 +32053,7 @@ 1 2 -9499071 +9509366 @@ -31495,19 +32063,19 @@ fieldoffsets -259539 +251575 id -259539 +251575 byteoffset -3914 +9022 bitoffset -85 +52 @@ -31521,7 +32089,7 @@ 1 2 -259539 +251575 @@ -31537,7 +32105,7 @@ 1 2 -259539 +251575 @@ -31553,42 +32121,27 @@ 1 2 -1689 +6132 2 3 -534 +782 3 -4 -194 - - -4 6 -340 +750 6 -11 -328 +17 +678 -11 -23 -328 - - -23 -84 -303 - - -90 -12369 -194 +17 +11685 +678 @@ -31604,12 +32157,12 @@ 1 2 -3853 +8579 2 -8 -60 +9 +443 @@ -31623,29 +32176,44 @@ 12 -1 -2 -36 +83 +84 +6 -2 -3 -12 +87 +88 +6 -3 -4 -12 +102 +103 +6 -4 -5 -12 +122 +123 +6 -21338 -21339 -12 +127 +128 +6 + + +153 +154 +6 + + +195 +196 +6 + + +37692 +37693 +6 @@ -31659,24 +32227,44 @@ 12 -1 -2 -36 +40 +41 +6 -2 -3 -24 +44 +45 +6 -3 -4 -12 +45 +46 +6 -322 -323 -12 +52 +53 +6 + + +54 +55 +6 + + +58 +59 +6 + + +66 +67 +6 + + +1383 +1384 +6 @@ -31686,11 +32274,11 @@ bitfield -13357 +13365 id -13357 +13365 bits @@ -31712,7 +32300,7 @@ 1 2 -13357 +13365 @@ -31728,7 +32316,7 @@ 1 2 -13357 +13365 @@ -31892,23 +32480,23 @@ initialisers -1685017 +1668506 init -1685017 +1668506 var -649685 +643667 expr -1685017 +1668506 location -321906 +318643 @@ -31922,7 +32510,7 @@ 1 2 -1685017 +1668506 @@ -31938,7 +32526,7 @@ 1 2 -1685017 +1668506 @@ -31954,7 +32542,7 @@ 1 2 -1685017 +1668506 @@ -31970,22 +32558,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32001,22 +32589,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32032,7 +32620,7 @@ 1 2 -649672 +643654 2 @@ -32053,7 +32641,7 @@ 1 2 -1685017 +1668506 @@ -32069,7 +32657,7 @@ 1 2 -1685017 +1668506 @@ -32085,7 +32673,7 @@ 1 2 -1685017 +1668506 @@ -32101,27 +32689,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32137,22 +32725,22 @@ 1 2 -271334 +268551 2 3 -25342 +25091 3 -24 -24155 +23 +23904 -24 +23 12632 -1074 +1096 @@ -32168,27 +32756,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32198,15 +32786,15 @@ expr_ancestor -67772 +68706 exp -67176 +68133 ancestor -49695 +51330 @@ -32220,12 +32808,12 @@ 1 2 -66605 +67584 2 4 -571 +549 @@ -32241,17 +32829,17 @@ 1 2 -37405 +39517 2 3 -10150 +9756 3 29 -2139 +2056 @@ -32261,19 +32849,19 @@ exprs -18449753 +18460593 id -18449753 +18460593 kind -393 +1168 location -6150603 +3836046 @@ -32287,7 +32875,7 @@ 1 2 -18449753 +18460593 @@ -32303,7 +32891,7 @@ 1 2 -18449753 +18460593 @@ -32317,69 +32905,69 @@ 12 -5 -28 -30 +1 +14 +105 -71 -82 -30 +15 +44 +93 -94 -255 -30 +47 +86 +93 -271 -627 -30 +90 +223 +93 -858 -1879 -30 +296 +463 +93 -2191 -3716 -30 +483 +715 +93 -4305 -6068 -30 +788 +2129 +93 -7004 -11661 -30 +2165 +2950 +93 -12107 -20202 -30 +3030 +4378 +93 -21965 -29561 -30 +4477 +6077 +93 -32830 -41032 -30 +6490 +17249 +93 -44670 -145995 -30 +19347 +188353 +93 -447805 -725766 -24 +191022 +403956 +35 @@ -32394,68 +32982,68 @@ 1 +4 +105 + + +6 +13 +105 + + +13 24 -30 +93 -27 -72 -30 +24 +38 +93 -77 -157 -30 +38 +134 +93 -171 -402 -30 +144 +259 +93 -422 -1083 -30 +269 +480 +93 -1179 -1862 -30 +481 +1074 +93 -2201 -4268 -30 +1095 +1411 +93 -4679 -6584 -30 +1422 +2045 +93 -6624 -11083 -30 +2059 +4557 +93 -11359 -12983 -30 +5888 +59687 +93 -17158 -28621 -30 - - -29980 -88945 -30 - - -128315 -425042 -24 +72153 +117893 +23 @@ -32471,22 +33059,37 @@ 1 2 -4450587 +1838158 2 3 -874643 +753582 3 -6 -496205 +4 +356208 -6 -22445 -329167 +4 +5 +276250 + + +5 +9 +301489 + + +9 +72 +287759 + + +72 +136887 +22598 @@ -32502,22 +33105,17 @@ 1 2 -4599301 +2734142 2 3 -812812 +859259 3 -5 -498909 - - -5 -33 -239579 +30 +242644 @@ -32527,19 +33125,19 @@ expr_types -18617706 +18629051 id -18444987 +18456012 typeid -1372691 +1345343 value_category -36 +35 @@ -32553,12 +33151,12 @@ 1 2 -18272500 +18283254 2 4 -172487 +172758 @@ -32574,7 +33172,7 @@ 1 2 -18444987 +18456012 @@ -32590,42 +33188,42 @@ 1 2 -530591 +526443 2 3 -259102 +254107 3 4 -113553 +110864 4 5 -95427 +92110 5 8 -122925 +118483 8 14 -105736 +102381 14 -46 -103864 +47 +101797 -46 -111456 -41489 +47 +123210 +39155 @@ -32641,17 +33239,17 @@ 1 2 -1207109 +1185928 2 3 -157753 +151877 3 4 -7828 +7536 @@ -32667,17 +33265,17 @@ 4533 4534 -12 +11 -340895 -340896 -12 +342547 +342548 +11 -1171875 -1171876 -12 +1232420 +1232421 +11 @@ -32691,19 +33289,19 @@ 12 -1340 -1341 -12 +1341 +1342 +11 -29733 -29734 -12 +29841 +29842 +11 -96111 -96112 -12 +98243 +98244 +11 @@ -32713,15 +33311,15 @@ new_allocated_type -29527 +28382 expr -29527 +28382 type_id -18234 +17527 @@ -32735,7 +33333,7 @@ 1 2 -29527 +28382 @@ -32751,22 +33349,22 @@ 1 2 -12667 +12175 2 3 -4035 +3879 3 9 -1446 +1390 10 92 -85 +81 @@ -32776,15 +33374,15 @@ new_array_allocated_type -5364 +5310 expr -5364 +5310 type_id -2306 +2283 @@ -32798,7 +33396,7 @@ 1 2 -5364 +5310 @@ -32819,12 +33417,12 @@ 2 3 -2043 +2022 3 7 -177 +176 8 @@ -33376,15 +33974,15 @@ condition_decl_bind -7646 +7349 expr -7646 +7349 decl -7646 +7349 @@ -33398,7 +33996,7 @@ 1 2 -7646 +7349 @@ -33414,7 +34012,7 @@ 1 2 -7646 +7349 @@ -33424,15 +34022,15 @@ typeid_bind -4899 +4708 expr -4899 +4708 type_id -2601 +2500 @@ -33446,7 +34044,7 @@ 1 2 -4899 +4708 @@ -33462,22 +34060,22 @@ 1 2 -1300 +1250 2 3 -996 +958 3 6 -230 +222 6 17 -72 +70 @@ -33487,15 +34085,15 @@ uuidof_bind -856 +848 expr -856 +848 type_id -652 +645 @@ -33509,7 +34107,7 @@ 1 2 -856 +848 @@ -33525,12 +34123,12 @@ 1 2 -481 +476 2 3 -138 +137 3 @@ -33545,15 +34143,15 @@ sizeof_bind -156997 +157089 expr -156997 +157089 type_id -2673 +2674 @@ -33567,7 +34165,7 @@ 1 2 -156997 +157089 @@ -33583,7 +34181,7 @@ 1 2 -1044 +1045 2 @@ -33681,11 +34279,11 @@ lambdas -12641 +12513 expr -12641 +12513 default_capture @@ -33707,7 +34305,7 @@ 1 2 -12641 +12513 @@ -33723,7 +34321,7 @@ 1 2 -12641 +12513 @@ -33812,23 +34410,23 @@ lambda_capture -21730 +21509 id -21730 +21509 lambda -10097 +9994 index -112 +110 field -21730 +21509 captured_by_reference @@ -33840,7 +34438,7 @@ location -14051 +13909 @@ -33854,7 +34452,7 @@ 1 2 -21730 +21509 @@ -33870,7 +34468,7 @@ 1 2 -21730 +21509 @@ -33886,7 +34484,7 @@ 1 2 -21730 +21509 @@ -33902,7 +34500,7 @@ 1 2 -21730 +21509 @@ -33918,7 +34516,7 @@ 1 2 -21730 +21509 @@ -33934,7 +34532,7 @@ 1 2 -21730 +21509 @@ -33950,27 +34548,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -33986,27 +34584,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34022,27 +34620,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34058,12 +34656,12 @@ 1 2 -9629 +9531 2 3 -467 +463 @@ -34079,7 +34677,7 @@ 1 2 -10077 +9975 2 @@ -34100,27 +34698,27 @@ 1 2 -5483 +5428 2 3 -2504 +2479 3 4 -1041 +1030 4 7 -823 +815 7 18 -243 +241 @@ -34429,7 +35027,7 @@ 2 3 -85 +84 @@ -34450,7 +35048,7 @@ 2 3 -46 +45 @@ -34562,7 +35160,7 @@ 1 2 -21730 +21509 @@ -34578,7 +35176,7 @@ 1 2 -21730 +21509 @@ -34594,7 +35192,7 @@ 1 2 -21730 +21509 @@ -34610,7 +35208,7 @@ 1 2 -21730 +21509 @@ -34626,7 +35224,7 @@ 1 2 -21730 +21509 @@ -34642,7 +35240,7 @@ 1 2 -21730 +21509 @@ -34900,17 +35498,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34926,12 +35524,12 @@ 1 2 -13115 +12982 2 68 -935 +926 @@ -34947,12 +35545,12 @@ 1 2 -13511 +13374 2 8 -540 +534 @@ -34968,17 +35566,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34994,7 +35592,7 @@ 1 2 -14032 +13889 2 @@ -35015,7 +35613,7 @@ 1 2 -14051 +13909 @@ -35141,19 +35739,19 @@ stmts -4943740 +4765273 id -4943740 +4765273 kind -230 +222 location -1317574 +1266448 @@ -35167,7 +35765,7 @@ 1 2 -4943740 +4765273 @@ -35183,7 +35781,7 @@ 1 2 -4943740 +4765273 @@ -35199,97 +35797,97 @@ 2 3 -12 +11 28 29 -12 +11 338 339 -12 +11 473 474 -12 +11 690 691 -12 +11 1560 1561 -12 +11 1757 1758 -12 +11 -2076 -2077 -12 +2080 +2081 +11 -2191 -2192 -12 +2193 +2194 +11 2707 2708 -12 +11 2748 2749 -12 +11 -2944 -2945 -12 +2946 +2947 +11 3296 3297 -12 +11 4540 4541 -12 +11 -28688 -28689 -12 +28694 +28695 +11 -53254 -53255 -12 +53369 +53370 +11 -85878 -85879 -12 +86211 +86212 +11 -98483 -98484 -12 +98824 +98825 +11 -115024 -115025 -12 +115365 +115366 +11 @@ -35305,97 +35903,97 @@ 2 3 -12 +11 23 24 -12 +11 106 107 -12 +11 112 113 -12 +11 178 179 -12 +11 252 253 -12 +11 296 297 -12 +11 661 662 -12 +11 663 664 -12 +11 991 992 -12 +11 1030 1031 -12 +11 1408 1409 -12 +11 1918 1919 -12 +11 2676 2677 -12 +11 10172 10173 -12 +11 10231 10232 -12 +11 22268 22269 -12 +11 26534 26535 -12 +11 31957 31958 -12 +11 @@ -35411,32 +36009,32 @@ 1 2 -779628 +747015 2 3 -179173 +173050 3 4 -120275 +116169 4 6 -106891 +103199 6 19 -102794 +99168 19 -4895 -28810 +4923 +27844 @@ -35452,12 +36050,12 @@ 1 2 -1291693 +1241571 2 9 -25881 +24876 @@ -35563,15 +36161,15 @@ if_then -524558 +524866 if_stmt -524558 +524866 then_id -524558 +524866 @@ -35585,7 +36183,7 @@ 1 2 -524558 +524866 @@ -35601,7 +36199,7 @@ 1 2 -524558 +524866 @@ -35611,15 +36209,15 @@ if_else -148234 +148322 if_stmt -148234 +148322 else_id -148234 +148322 @@ -35633,7 +36231,7 @@ 1 2 -148234 +148322 @@ -35649,7 +36247,7 @@ 1 2 -148234 +148322 @@ -35755,15 +36353,15 @@ while_body -32907 +31630 while_stmt -32907 +31630 body_id -32907 +31630 @@ -35777,7 +36375,7 @@ 1 2 -32907 +31630 @@ -35793,7 +36391,7 @@ 1 2 -32907 +31630 @@ -35803,15 +36401,15 @@ do_body -149900 +149988 do_stmt -149900 +149988 body_id -149900 +149988 @@ -35825,7 +36423,7 @@ 1 2 -149900 +149988 @@ -35841,7 +36439,7 @@ 1 2 -149900 +149988 @@ -35851,11 +36449,11 @@ switch_case -281530 +281695 switch_stmt -55225 +55258 index @@ -35863,7 +36461,7 @@ case_id -281530 +281695 @@ -35877,17 +36475,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -35903,17 +36501,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -36031,7 +36629,7 @@ 1 2 -281530 +281695 @@ -36047,7 +36645,7 @@ 1 2 -281530 +281695 @@ -36057,15 +36655,15 @@ switch_body -55225 +55258 switch_stmt -55225 +55258 body_id -55225 +55258 @@ -36079,7 +36677,7 @@ 1 2 -55225 +55258 @@ -36095,7 +36693,7 @@ 1 2 -55225 +55258 @@ -36105,15 +36703,15 @@ for_initialization -29922 +29619 for_stmt -29922 +29619 init_id -29922 +29619 @@ -36127,7 +36725,7 @@ 1 2 -29922 +29619 @@ -36143,7 +36741,7 @@ 1 2 -29922 +29619 @@ -36153,15 +36751,15 @@ for_condition -31781 +31459 for_stmt -31781 +31459 condition_id -31781 +31459 @@ -36175,7 +36773,7 @@ 1 2 -31781 +31459 @@ -36191,7 +36789,7 @@ 1 2 -31781 +31459 @@ -36201,15 +36799,15 @@ for_update -29659 +29358 for_stmt -29659 +29358 update_id -29659 +29358 @@ -36223,7 +36821,7 @@ 1 2 -29659 +29358 @@ -36239,7 +36837,7 @@ 1 2 -29659 +29358 @@ -36249,15 +36847,15 @@ for_body -32387 +32059 for_stmt -32387 +32059 body_id -32387 +32059 @@ -36271,7 +36869,7 @@ 1 2 -32387 +32059 @@ -36287,7 +36885,7 @@ 1 2 -32387 +32059 @@ -36297,19 +36895,19 @@ stmtparents -4168478 +4131960 id -4168478 +4131960 index -12799 +836 parent -1762006 +1583254 @@ -36323,7 +36921,7 @@ 1 2 -4168478 +4131960 @@ -36339,7 +36937,7 @@ 1 2 -4168478 +4131960 @@ -36355,52 +36953,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36416,52 +37019,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36477,32 +37085,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 +9 +119501 -6 -17 -133386 - - -17 -1943 -12819 +9 +465 +100269 @@ -36518,32 +37121,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 +9 +119501 -6 -17 -133386 - - -17 -1943 -12819 +9 +465 +100269 @@ -36553,26 +37151,26 @@ ishandler -21888 +21666 block -21888 +21666 successors -17214104 +17224218 from -16042874 +16052300 to -16040997 +16050421 @@ -36586,12 +37184,12 @@ 1 2 -15044821 +15053661 2 156 -998052 +998638 @@ -36607,12 +37205,12 @@ 1 2 -15328885 +15337891 2 419 -712111 +712530 @@ -36622,15 +37220,15 @@ truecond -966805 +967373 from -966805 +967373 to -937112 +937663 @@ -36644,7 +37242,7 @@ 1 2 -966805 +967373 @@ -36660,12 +37258,12 @@ 1 2 -913540 +914077 2 21 -23572 +23585 @@ -36675,15 +37273,15 @@ falsecond -966805 +967373 from -966805 +967373 to -812105 +812583 @@ -36697,7 +37295,7 @@ 1 2 -966805 +967373 @@ -36713,17 +37311,17 @@ 1 2 -698749 +699160 2 3 -87006 +87057 3 25 -26349 +26365 @@ -36733,11 +37331,11 @@ stmt_decl_bind -538233 +532777 stmt -531279 +525894 num @@ -36745,7 +37343,7 @@ decl -538233 +532777 @@ -36759,12 +37357,12 @@ 1 2 -525776 +520447 2 9 -5503 +5447 @@ -36780,12 +37378,12 @@ 1 2 -525756 +520427 2 9 -5523 +5467 @@ -36903,7 +37501,7 @@ 1 2 -538233 +532777 @@ -36919,7 +37517,7 @@ 1 2 -538233 +532777 @@ -36929,19 +37527,19 @@ stmt_decl_entry_bind -519726 +520031 stmt -474524 +474803 num -491 +492 decl_entry -495657 +495948 @@ -36955,12 +37553,12 @@ 1 2 -441842 +442101 2 274 -32682 +32702 @@ -36976,12 +37574,12 @@ 1 2 -441842 +442101 2 15 -32682 +32702 @@ -37064,12 +37662,12 @@ 1 2 -483634 +483918 2 85 -12022 +12029 @@ -37085,7 +37683,7 @@ 1 2 -495588 +495879 2 @@ -37100,15 +37698,15 @@ blockscope -1398256 +1347984 block -1398256 +1347984 enclosing -1254288 +1209602 @@ -37122,7 +37720,7 @@ 1 2 -1398256 +1347984 @@ -37138,12 +37736,12 @@ 1 2 -1171636 +1130157 2 509 -82651 +79444 @@ -37153,19 +37751,19 @@ jumpinfo -366503 +366719 id -366503 +366719 str -6361 +6365 target -85508 +85558 @@ -37179,7 +37777,7 @@ 1 2 -366503 +366719 @@ -37195,7 +37793,7 @@ 1 2 -366503 +366719 @@ -37216,12 +37814,12 @@ 2 3 -3507 +3509 3 4 -835 +836 4 @@ -37231,12 +37829,12 @@ 5 7 -491 +492 7 15 -500 +501 15 @@ -37257,12 +37855,12 @@ 1 2 -5095 +5098 2 3 -700 +701 3 @@ -37293,32 +37891,32 @@ 2 3 -21251 +21263 3 4 -7559 +7564 4 5 -3816 +3818 5 6 -39695 +39718 6 7 -11019 +11025 7 162 -1880 +1882 @@ -37334,7 +37932,7 @@ 1 2 -85508 +85558 @@ -37344,19 +37942,19 @@ preprocdirects -1456121 +1399618 id -1456121 +1399618 kind -158 +151 location -1449131 +1392900 @@ -37370,7 +37968,7 @@ 1 2 -1456121 +1399618 @@ -37386,7 +37984,7 @@ 1 2 -1456121 +1399618 @@ -37402,67 +38000,67 @@ 4 5 -12 +11 8 9 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26464 26465 -12 +11 27121 27122 -12 +11 28787 28788 -12 +11 @@ -37478,67 +38076,67 @@ 4 5 -12 +11 7 8 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26122 26123 -12 +11 27121 27122 -12 +11 28555 28556 -12 +11 @@ -37554,12 +38152,12 @@ 1 2 -1448766 +1392549 2 234 -364 +350 @@ -37575,7 +38173,7 @@ 1 2 -1449131 +1392900 @@ -37585,15 +38183,15 @@ preprocpair -416102 +399956 begin -329694 +316901 elseelifend -416102 +399956 @@ -37607,17 +38205,17 @@ 1 2 -261399 +251256 2 3 -60247 +57909 3 53 -8047 +7735 @@ -37633,7 +38231,7 @@ 1 2 -416102 +399956 @@ -37643,41 +38241,41 @@ preproctrue -183112 +176006 branch -183112 +176006 preprocfalse -130000 +124956 branch -130000 +124956 preproctext -1062775 +1021536 id -1062775 +1021536 head -510083 +490290 body -192959 +185471 @@ -37691,7 +38289,7 @@ 1 2 -1062775 +1021536 @@ -37707,7 +38305,7 @@ 1 2 -1062775 +1021536 @@ -37723,22 +38321,22 @@ 1 2 -380459 +365696 2 3 -86116 +82774 3 19 -38414 +36923 19 752 -5093 +4895 @@ -37754,12 +38352,12 @@ 1 2 -486208 +467341 2 38 -23875 +22948 @@ -37775,12 +38373,12 @@ 1 2 -181252 +174219 2 64395 -11706 +11252 @@ -37796,12 +38394,12 @@ 1 2 -182893 +175796 2 21671 -10065 +9674 @@ -37811,15 +38409,15 @@ includes -321805 +309317 id -321805 +309317 included -60162 +57827 @@ -37833,7 +38431,7 @@ 1 2 -321805 +309317 @@ -37849,37 +38447,37 @@ 1 2 -29503 +28358 2 3 -9895 +9511 3 4 -5117 +4919 4 6 -5348 +5141 6 11 -4643 +4463 11 41 -4558 +4381 41 763 -1094 +1051 @@ -37889,15 +38487,15 @@ link_targets -644 +619 id -644 +619 binary -644 +619 @@ -37911,7 +38509,7 @@ 1 2 -644 +619 @@ -37927,7 +38525,7 @@ 1 2 -644 +619 @@ -37937,15 +38535,15 @@ link_parent -19143690 +19072521 element -5076549 +5117392 link_target -644 +619 @@ -37959,32 +38557,32 @@ 1 2 -1439430 +1455425 2 3 -1904730 +1924496 3 4 -772395 +779113 4 6 -426167 +434215 6 -27 -383109 +28 +394382 -27 +28 45 -150715 +129758 @@ -38000,67 +38598,67 @@ 2 3 -97 +93 5 557 -48 +46 -2555 -5912 -48 +2662 +6059 +46 -6322 -8240 -48 +6479 +8402 +46 -9873 -12705 -48 +10060 +12929 +46 -12726 -19568 -48 +13044 +20082 +46 -24613 -26319 -48 +24978 +26985 +46 -26410 -31881 -48 +27088 +32537 +46 -32502 -37729 -48 +33104 +38465 +46 -39858 -40615 -48 +41123 +42511 +46 -43096 -52498 -48 +44410 +55889 +46 -53361 -126529 -48 +55937 +132605 +46 -345660 -345661 -12 +362472 +362473 +11 diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp new file mode 100644 index 00000000000..5e4f2f97f46 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -0,0 +1,46 @@ +int source(); +void sink(int); + +// This class has the opposite behavior of what the member function names suggest. +struct Top { + virtual int isSource1() { return 0; } + virtual int isSource2() { return 0; } + virtual void isSink(int x) { } + virtual int notSource1() { return source(); } + virtual int notSource2() { return source(); } + virtual void notSink(int x) { sink(x); } +}; + +// This class has the correct behavior for just the functions ending in 2. +struct Middle : Top { + int isSource2() override { return source(); } + int notSource2() override { return 0; } +}; + +// This class has all the behavior suggested by the function names. +struct Bottom : Middle { + int isSource1() override { return source(); } + void isSink(int x) override { sink(x); } + int notSource1() override { return 0; } + void notSink(int x) override { } +}; + +void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { + Top *topPtr = bottomPtr, &topRef = bottomRef; + + sink(topPtr->isSource1()); // flow [NOT DETECTED by AST] + sink(topPtr->isSource2()); // flow [NOT DETECTED by AST] + topPtr->isSink(source()); // flow [NOT DETECTED by AST] + + sink(topPtr->notSource1()); // no flow [FALSE POSITIVE] + sink(topPtr->notSource2()); // no flow [FALSE POSITIVE] + topPtr->notSink(source()); // no flow [FALSE POSITIVE] + + sink(topRef.isSource1()); // flow [NOT DETECTED by AST] + sink(topRef.isSource2()); // flow [NOT DETECTED by AST] + topRef.isSink(source()); // flow [NOT DETECTED by AST] + + sink(topRef.notSource1()); // no flow [FALSE POSITIVE] + sink(topRef.notSource2()); // no flow [FALSE POSITIVE] + topRef.notSink(source()); // no flow [FALSE POSITIVE] +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected index 6527db4b77e..24fa6fdb5bd 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected @@ -15,6 +15,12 @@ | clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source | | clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | 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: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: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 | | lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 7d0d4e7d72e..9b8be3abd1e 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -5,6 +5,12 @@ | clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:31:16:31:24 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:39:15:39:23 | IR only | +| dispatch.cpp:33:18:33:23 | dispatch.cpp:23:38:23:38 | IR only | +| dispatch.cpp:41:17:41:22 | dispatch.cpp:23:38:23:38 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 9b67a013a58..651e580a105 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -12,6 +12,18 @@ | 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 | diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index f40460f4d91..ac518b5dd79 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,6 +1,16 @@ +| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 | @@ -16,32 +26,61 @@ | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:14 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:150:18:150:27 | ConvertToNonVirtualBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:151:5:151:14 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | -| escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:152:19:152:28 | ConvertToNonVirtualBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | | escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | | escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 | | escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 | +| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 | | escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | +| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 | +| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | +| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | | escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | +| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 | +| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | | escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 | +| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 19a4288a4c4..dab6a40fae6 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -67,31 +67,7 @@ bad_asts.cpp: # 5| params: #-----| 0: [Parameter] p#0 #-----| Type = [RValueReferenceType] S && -# 9| [MemberFunction] int Bad::S::MemberFunction(int) -# 9| params: -# 9| 0: [Parameter] y -# 9| Type = [IntType] int -# 9| body: [Block] { ... } -# 10| 0: [ReturnStmt] return ... -# 10| 0: [AddExpr] ... + ... -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 0: [AddExpr] ... + ... -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 0: [Literal] Unknown literal -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue -# 10| 1: [PointerFieldAccess] x -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue(load) -#-----| -1: [ThisExpr] this -#-----| Type = [PointerType] S * -#-----| ValueCategory = prvalue(load) -# 10| 1: [VariableAccess] y -# 10| Type = [IntType] int -# 10| ValueCategory = prvalue(load) -# 9| [TopLevelFunction] int MemberFunction(int) +# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -116,6 +92,31 @@ bad_asts.cpp: # 10| 1: [VariableAccess] y # 10| Type = [IntType] int # 10| ValueCategory = prvalue(load) +# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) +# 9| params: +# 9| 0: [Parameter] y +# 9| Type = [IntType] int +# 9| body: [Block] { ... } +# 10| 0: [ReturnStmt] return ... +# 10| 0: [AddExpr] ... + ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| 0: [AddExpr] ... + ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| 0: [Literal] t +# 10| Type = [IntType] int +# 10| Value = [Literal] t +# 10| ValueCategory = prvalue +# 10| 1: [PointerFieldAccess] x +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) +#-----| -1: [ThisExpr] this +#-----| Type = [PointerType] S * +#-----| ValueCategory = prvalue(load) +# 10| 1: [VariableAccess] y +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) # 14| [TopLevelFunction] void Bad::CallBadMemberFunction() # 14| params: # 14| body: [Block] { ... } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 90c3061114e..1fedd09d5a6 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,4 +1,28 @@ bad_asts.cpp: +# 9| int Bad::S::MemberFunction(int) +# 9| Block 0 +# 9| v0_0(void) = EnterFunction : +# 9| mu0_1(unknown) = AliasedDefinition : +# 9| mu0_2(unknown) = UnmodeledDefinition : +# 9| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[y] : +# 9| mu0_5(int) = InitializeParameter[y] : &:r0_4 +# 10| r0_6(glval) = VariableAddress[#return] : +# 10| r0_7(int) = Constant[6] : +#-----| r0_8(S *) = CopyValue : r0_3 +# 10| r0_9(glval) = FieldAddress[x] : r0_8 +# 10| r0_10(int) = Load : &:r0_9, ~mu0_2 +# 10| r0_11(int) = Add : r0_7, r0_10 +# 10| r0_12(glval) = VariableAddress[y] : +# 10| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 10| r0_14(int) = Add : r0_11, r0_13 +# 10| mu0_15(int) = Store : &:r0_6, r0_14 +# 9| r0_16(glval) = VariableAddress[#return] : +# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 9| v0_18(void) = UnmodeledUse : mu* +# 9| v0_19(void) = AliasedUse : ~mu0_2 +# 9| v0_20(void) = ExitFunction : + # 14| void Bad::CallBadMemberFunction() # 14| Block 0 # 14| v0_0(void) = EnterFunction : @@ -44,14 +68,15 @@ bad_asts.cpp: # 27| r0_5(glval) = VariableAddress[b] : # 27| r0_6(glval) = VariableAddress[a] : # 27| r0_7(Point &) = Load : &:r0_6, ~mu0_2 -# 27| r0_8(glval) = Convert : r0_7 -# 27| r0_9(Point) = Load : &:r0_8, ~mu0_2 -# 27| mu0_10(Point) = Store : &:r0_5, r0_9 -# 28| v0_11(void) = NoOp : -# 26| v0_12(void) = ReturnVoid : -# 26| v0_13(void) = UnmodeledUse : mu* -# 26| v0_14(void) = AliasedUse : ~mu0_2 -# 26| v0_15(void) = ExitFunction : +# 27| r0_8(glval) = CopyValue : r0_7 +# 27| r0_9(glval) = Convert : r0_8 +# 27| r0_10(Point) = Load : &:r0_9, ~mu0_2 +# 27| mu0_11(Point) = Store : &:r0_5, r0_10 +# 28| v0_12(void) = NoOp : +# 26| v0_13(void) = ReturnVoid : +# 26| v0_14(void) = UnmodeledUse : mu* +# 26| v0_15(void) = AliasedUse : ~mu0_2 +# 26| v0_16(void) = ExitFunction : # 30| void Bad::errorExpr() # 30| Block 0 @@ -82,12 +107,13 @@ clang.cpp: # 5| mu0_2(unknown) = UnmodeledDefinition : # 6| r0_3(glval) = VariableAddress[#return] : # 6| r0_4(glval) = VariableAddress[globalInt] : -# 6| mu0_5(int *) = Store : &:r0_3, r0_4 -# 5| r0_6(glval) = VariableAddress[#return] : -# 5| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 5| v0_8(void) = UnmodeledUse : mu* -# 5| v0_9(void) = AliasedUse : ~mu0_2 -# 5| v0_10(void) = ExitFunction : +# 6| r0_5(int *) = CopyValue : r0_4 +# 6| mu0_6(int *) = Store : &:r0_3, r0_5 +# 5| r0_7(glval) = VariableAddress[#return] : +# 5| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 5| v0_9(void) = UnmodeledUse : mu* +# 5| v0_10(void) = AliasedUse : ~mu0_2 +# 5| v0_11(void) = ExitFunction : ir.cpp: # 1| void Constants() @@ -509,20 +535,24 @@ ir.cpp: # 110| r0_9(int) = Constant[1] : # 110| r0_10(int) = Add : r0_8, r0_9 # 110| mu0_11(int) = Store : &:r0_7, r0_10 -# 110| r0_12(glval) = VariableAddress[p] : -# 110| mu0_13(int *) = Store : &:r0_12, r0_7 -# 111| r0_14(glval) = VariableAddress[x] : -# 111| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 111| r0_16(int) = Constant[1] : -# 111| r0_17(int) = Sub : r0_15, r0_16 -# 111| mu0_18(int) = Store : &:r0_14, r0_17 -# 111| r0_19(glval) = VariableAddress[p] : -# 111| mu0_20(int *) = Store : &:r0_19, r0_14 -# 112| v0_21(void) = NoOp : -# 107| v0_22(void) = ReturnVoid : -# 107| v0_23(void) = UnmodeledUse : mu* -# 107| v0_24(void) = AliasedUse : ~mu0_2 -# 107| v0_25(void) = ExitFunction : +# 110| r0_12(glval) = CopyValue : r0_7 +# 110| r0_13(int *) = CopyValue : r0_12 +# 110| r0_14(glval) = VariableAddress[p] : +# 110| mu0_15(int *) = Store : &:r0_14, r0_13 +# 111| r0_16(glval) = VariableAddress[x] : +# 111| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 111| r0_18(int) = Constant[1] : +# 111| r0_19(int) = Sub : r0_17, r0_18 +# 111| mu0_20(int) = Store : &:r0_16, r0_19 +# 111| r0_21(glval) = CopyValue : r0_16 +# 111| r0_22(int *) = CopyValue : r0_21 +# 111| r0_23(glval) = VariableAddress[p] : +# 111| mu0_24(int *) = Store : &:r0_23, r0_22 +# 112| v0_25(void) = NoOp : +# 107| v0_26(void) = ReturnVoid : +# 107| v0_27(void) = UnmodeledUse : mu* +# 107| v0_28(void) = AliasedUse : ~mu0_2 +# 107| v0_29(void) = ExitFunction : # 114| void FloatOps(double, double) # 114| Block 0 @@ -1583,17 +1613,18 @@ ir.cpp: # 342| r0_5(int) = Constant[1] : # 342| r0_6(glval) = VariableAddress[p] : # 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 -# 342| mu0_8(int) = Store : &:r0_7, r0_5 -# 343| r0_9(glval) = VariableAddress[#return] : -# 343| r0_10(glval) = VariableAddress[p] : -# 343| r0_11(int *) = Load : &:r0_10, ~mu0_2 -# 343| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 343| mu0_13(int) = Store : &:r0_9, r0_12 -# 341| r0_14(glval) = VariableAddress[#return] : -# 341| v0_15(void) = ReturnValue : &:r0_14, ~mu0_2 -# 341| v0_16(void) = UnmodeledUse : mu* -# 341| v0_17(void) = AliasedUse : ~mu0_2 -# 341| v0_18(void) = ExitFunction : +# 342| r0_8(glval) = CopyValue : r0_7 +# 342| mu0_9(int) = Store : &:r0_8, r0_5 +# 343| r0_10(glval) = VariableAddress[#return] : +# 343| r0_11(glval) = VariableAddress[p] : +# 343| r0_12(int *) = Load : &:r0_11, ~mu0_2 +# 343| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 343| mu0_14(int) = Store : &:r0_10, r0_13 +# 341| r0_15(glval) = VariableAddress[#return] : +# 341| v0_16(void) = ReturnValue : &:r0_15, ~mu0_2 +# 341| v0_17(void) = UnmodeledUse : mu* +# 341| v0_18(void) = AliasedUse : ~mu0_2 +# 341| v0_19(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -1602,12 +1633,13 @@ ir.cpp: # 348| mu0_2(unknown) = UnmodeledDefinition : # 349| r0_3(glval) = VariableAddress[#return] : # 349| r0_4(glval) = VariableAddress[g] : -# 349| mu0_5(int *) = Store : &:r0_3, r0_4 -# 348| r0_6(glval) = VariableAddress[#return] : -# 348| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 348| v0_8(void) = UnmodeledUse : mu* -# 348| v0_9(void) = AliasedUse : ~mu0_2 -# 348| v0_10(void) = ExitFunction : +# 349| r0_5(int *) = CopyValue : r0_4 +# 349| mu0_6(int *) = Store : &:r0_3, r0_5 +# 348| r0_7(glval) = VariableAddress[#return] : +# 348| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 348| v0_9(void) = UnmodeledUse : mu* +# 348| v0_10(void) = AliasedUse : ~mu0_2 +# 348| v0_11(void) = ExitFunction : # 352| void Break(int) # 352| Block 0 @@ -1761,12 +1793,13 @@ ir.cpp: # 381| r0_15(int) = Load : &:r0_14, ~mu0_2 # 381| r0_16(int) = Call : func:r0_11, 0:r0_13, 1:r0_15 # 381| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 381| mu0_18(int) = Store : &:r0_7, r0_16 -# 380| r0_19(glval) = VariableAddress[#return] : -# 380| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 380| v0_21(void) = UnmodeledUse : mu* -# 380| v0_22(void) = AliasedUse : ~mu0_2 -# 380| v0_23(void) = ExitFunction : +# 381| r0_18(int) = CopyValue : r0_16 +# 381| mu0_19(int) = Store : &:r0_7, r0_18 +# 380| r0_20(glval) = VariableAddress[#return] : +# 380| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 380| v0_22(void) = UnmodeledUse : mu* +# 380| v0_23(void) = AliasedUse : ~mu0_2 +# 380| v0_24(void) = ExitFunction : # 384| void Switch(int) # 384| Block 0 @@ -1887,12 +1920,13 @@ ir.cpp: # 430| r0_15(glval) = VariableAddress[p] : # 430| r0_16(glval) = VariableAddress[pt] : # 430| r0_17(glval) = FieldAddress[y] : r0_16 -# 430| mu0_18(int *) = Store : &:r0_15, r0_17 -# 431| v0_19(void) = NoOp : -# 426| v0_20(void) = ReturnVoid : -# 426| v0_21(void) = UnmodeledUse : mu* -# 426| v0_22(void) = AliasedUse : ~mu0_2 -# 426| v0_23(void) = ExitFunction : +# 430| r0_18(int *) = CopyValue : r0_17 +# 430| mu0_19(int *) = Store : &:r0_15, r0_18 +# 431| v0_20(void) = NoOp : +# 426| v0_21(void) = ReturnVoid : +# 426| v0_22(void) = UnmodeledUse : mu* +# 426| v0_23(void) = AliasedUse : ~mu0_2 +# 426| v0_24(void) = ExitFunction : # 433| void LogicalOr(bool, bool) # 433| Block 0 @@ -2666,64 +2700,65 @@ ir.cpp: # 571| mu0_1(unknown) = AliasedDefinition : # 571| mu0_2(unknown) = UnmodeledDefinition : # 572| r0_3(glval) = VariableAddress[a_pad] : -# 572| r0_4(glval) = StringConstant[""] : -# 572| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 -# 572| mu0_6(char[1]) = Store : &:r0_3, r0_5 -# 572| r0_7(unknown[31]) = Constant[0] : -# 572| r0_8(int) = Constant[1] : -# 572| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 572| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 573| r0_11(glval) = VariableAddress[a_nopad] : -# 573| r0_12(glval) = StringConstant["foo"] : -# 573| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 -# 573| mu0_14(char[4]) = Store : &:r0_11, r0_13 -# 574| r0_15(glval) = VariableAddress[a_infer] : -# 574| r0_16(glval) = StringConstant["blah"] : -# 574| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 -# 574| mu0_18(char[5]) = Store : &:r0_15, r0_17 -# 575| r0_19(glval) = VariableAddress[b] : -# 575| mu0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 576| r0_21(glval) = VariableAddress[c] : -# 576| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 576| r0_23(int) = Constant[0] : -# 576| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 576| r0_25(unknown[2]) = Constant[0] : -# 576| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 577| r0_27(glval) = VariableAddress[d] : -# 577| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 577| r0_29(int) = Constant[0] : -# 577| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 577| r0_31(char) = Constant[0] : -# 577| mu0_32(char) = Store : &:r0_30, r0_31 -# 577| r0_33(int) = Constant[1] : -# 577| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 -# 577| r0_35(char) = Constant[0] : -# 577| mu0_36(char) = Store : &:r0_34, r0_35 -# 578| r0_37(glval) = VariableAddress[e] : -# 578| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 -# 578| r0_39(int) = Constant[0] : -# 578| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 -# 578| r0_41(char) = Constant[0] : -# 578| mu0_42(char) = Store : &:r0_40, r0_41 -# 578| r0_43(int) = Constant[1] : -# 578| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 -# 578| r0_45(char) = Constant[1] : -# 578| mu0_46(char) = Store : &:r0_44, r0_45 -# 579| r0_47(glval) = VariableAddress[f] : -# 579| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 -# 579| r0_49(int) = Constant[0] : -# 579| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 -# 579| r0_51(char) = Constant[0] : -# 579| mu0_52(char) = Store : &:r0_50, r0_51 -# 579| r0_53(int) = Constant[1] : -# 579| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 -# 579| r0_55(unknown[2]) = Constant[0] : -# 579| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 -# 580| v0_57(void) = NoOp : -# 571| v0_58(void) = ReturnVoid : -# 571| v0_59(void) = UnmodeledUse : mu* -# 571| v0_60(void) = AliasedUse : ~mu0_2 -# 571| v0_61(void) = ExitFunction : +# 572| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 572| r0_5(glval) = 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) = PointerAdd[1] : r0_3, r0_9 +# 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 573| r0_12(glval) = VariableAddress[a_nopad] : +# 573| r0_13(glval) = 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) = VariableAddress[a_infer] : +# 574| r0_17(glval) = 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) = VariableAddress[b] : +# 575| mu0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 576| r0_22(glval) = VariableAddress[c] : +# 576| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 576| r0_24(int) = Constant[0] : +# 576| r0_25(glval) = 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) = VariableAddress[d] : +# 577| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 577| r0_30(int) = Constant[0] : +# 577| r0_31(glval) = 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) = 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) = VariableAddress[e] : +# 578| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 578| r0_40(int) = Constant[0] : +# 578| r0_41(glval) = 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) = 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) = VariableAddress[f] : +# 579| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 579| r0_50(int) = Constant[0] : +# 579| r0_51(glval) = 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) = 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 : # 584| void VarArgs() # 584| Block 0 @@ -2757,19 +2792,25 @@ ir.cpp: # 591| r0_4(..(*)(..)) = FunctionAddress[FuncPtrTarget] : # 591| mu0_5(..(*)(..)) = Store : &:r0_3, r0_4 # 592| r0_6(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 592| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : -# 592| mu0_8(..(*)(..)) = Store : &:r0_7, r0_6 -# 593| r0_9(..(*)(..)) = FunctionAddress[FuncPtrTarget] : -# 593| r0_10(glval<..(*)(..)>) = VariableAddress[pfn] : -# 593| mu0_11(..(*)(..)) = Store : &:r0_10, r0_9 -# 594| r0_12(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 594| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : -# 594| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 -# 595| v0_15(void) = NoOp : -# 590| v0_16(void) = ReturnVoid : -# 590| v0_17(void) = UnmodeledUse : mu* -# 590| v0_18(void) = AliasedUse : ~mu0_2 -# 590| v0_19(void) = ExitFunction : +# 592| r0_7(..(*)(..)) = CopyValue : r0_6 +# 592| r0_8(glval<..(*)(..)>) = VariableAddress[pfn] : +# 592| mu0_9(..(*)(..)) = Store : &:r0_8, r0_7 +# 593| r0_10(..(*)(..)) = FunctionAddress[FuncPtrTarget] : +# 593| r0_11(..(*)(..)) = CopyValue : r0_10 +# 593| r0_12(glval<..(*)(..)>) = VariableAddress[pfn] : +# 593| mu0_13(..(*)(..)) = Store : &:r0_12, r0_11 +# 594| r0_14(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 594| r0_15(..(*)(..)) = CopyValue : r0_14 +# 594| r0_16(..(*)(..)) = CopyValue : r0_15 +# 594| r0_17(..(*)(..)) = CopyValue : r0_16 +# 594| r0_18(..(*)(..)) = CopyValue : r0_17 +# 594| r0_19(glval<..(*)(..)>) = VariableAddress[pfn] : +# 594| mu0_20(..(*)(..)) = Store : &:r0_19, r0_18 +# 595| v0_21(void) = NoOp : +# 590| v0_22(void) = ReturnVoid : +# 590| v0_23(void) = UnmodeledUse : mu* +# 590| v0_24(void) = AliasedUse : ~mu0_2 +# 590| v0_25(void) = ExitFunction : # 615| void DeclareObject() # 615| Block 0 @@ -2820,32 +2861,33 @@ ir.cpp: # 622| mu0_8(String) = InitializeParameter[s] : &:r0_7 # 623| r0_9(glval) = VariableAddress[r] : # 623| r0_10(String &) = Load : &:r0_9, ~mu0_2 -# 623| r0_11(glval) = Convert : r0_10 -# 623| r0_12(glval) = FunctionAddress[c_str] : -# 623| r0_13(char *) = Call : func:r0_12, this:r0_11 -# 623| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 623| v0_15(void) = ^BufferReadSideEffect[-1] : &:r0_11, ~mu0_2 -# 623| mu0_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -# 624| r0_17(glval) = VariableAddress[p] : -# 624| r0_18(String *) = Load : &:r0_17, ~mu0_2 -# 624| r0_19(String *) = Convert : r0_18 -# 624| r0_20(glval) = FunctionAddress[c_str] : -# 624| r0_21(char *) = Call : func:r0_20, this:r0_19 -# 624| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -# 624| v0_23(void) = ^BufferReadSideEffect[-1] : &:r0_19, ~mu0_2 -# 624| mu0_24(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -# 625| r0_25(glval) = VariableAddress[s] : -# 625| r0_26(glval) = Convert : r0_25 -# 625| r0_27(glval) = FunctionAddress[c_str] : -# 625| r0_28(char *) = Call : func:r0_27, this:r0_26 -# 625| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 625| v0_30(void) = ^BufferReadSideEffect[-1] : &:r0_26, ~mu0_2 -# 625| mu0_31(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_26 -# 626| v0_32(void) = NoOp : -# 622| v0_33(void) = ReturnVoid : -# 622| v0_34(void) = UnmodeledUse : mu* -# 622| v0_35(void) = AliasedUse : ~mu0_2 -# 622| v0_36(void) = ExitFunction : +# 623| r0_11(glval) = CopyValue : r0_10 +# 623| r0_12(glval) = Convert : r0_11 +# 623| r0_13(glval) = FunctionAddress[c_str] : +# 623| r0_14(char *) = Call : func:r0_13, this:r0_12 +# 623| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 623| v0_16(void) = ^BufferReadSideEffect[-1] : &:r0_12, ~mu0_2 +# 623| mu0_17(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_12 +# 624| r0_18(glval) = VariableAddress[p] : +# 624| r0_19(String *) = Load : &:r0_18, ~mu0_2 +# 624| r0_20(String *) = Convert : r0_19 +# 624| r0_21(glval) = FunctionAddress[c_str] : +# 624| r0_22(char *) = Call : func:r0_21, this:r0_20 +# 624| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 +# 624| v0_24(void) = ^BufferReadSideEffect[-1] : &:r0_20, ~mu0_2 +# 624| mu0_25(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_20 +# 625| r0_26(glval) = VariableAddress[s] : +# 625| r0_27(glval) = Convert : r0_26 +# 625| r0_28(glval) = FunctionAddress[c_str] : +# 625| r0_29(char *) = Call : func:r0_28, this:r0_27 +# 625| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 +# 625| v0_31(void) = ^BufferReadSideEffect[-1] : &:r0_27, ~mu0_2 +# 625| mu0_32(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 +# 626| v0_33(void) = NoOp : +# 622| v0_34(void) = ReturnVoid : +# 622| v0_35(void) = UnmodeledUse : mu* +# 622| v0_36(void) = AliasedUse : ~mu0_2 +# 622| v0_37(void) = ExitFunction : # 630| int C::StaticMemberFunction(int) # 630| Block 0 @@ -2912,34 +2954,36 @@ ir.cpp: # 643| mu0_7(int) = Store : &:r0_6, r0_4 # 644| r0_8(int) = Constant[1] : # 644| r0_9(C *) = CopyValue : r0_3 -# 644| r0_10(glval) = FieldAddress[m_a] : r0_9 -# 644| mu0_11(int) = Store : &:r0_10, r0_8 -# 645| r0_12(int) = Constant[2] : -#-----| r0_13(C *) = CopyValue : r0_3 -# 645| r0_14(glval) = FieldAddress[m_a] : r0_13 -# 645| mu0_15(int) = Store : &:r0_14, r0_12 -# 646| r0_16(glval) = VariableAddress[x] : -# 646| mu0_17(int) = Uninitialized[x] : &:r0_16 -# 647| r0_18(C *) = CopyValue : r0_3 -# 647| r0_19(glval) = FieldAddress[m_a] : r0_18 -# 647| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 647| r0_21(glval) = VariableAddress[x] : -# 647| mu0_22(int) = Store : &:r0_21, r0_20 -# 648| r0_23(C *) = CopyValue : r0_3 -# 648| r0_24(glval) = FieldAddress[m_a] : r0_23 -# 648| r0_25(int) = Load : &:r0_24, ~mu0_2 -# 648| r0_26(glval) = VariableAddress[x] : -# 648| mu0_27(int) = Store : &:r0_26, r0_25 -#-----| r0_28(C *) = CopyValue : r0_3 -# 649| r0_29(glval) = FieldAddress[m_a] : r0_28 -# 649| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 649| r0_31(glval) = VariableAddress[x] : -# 649| mu0_32(int) = Store : &:r0_31, r0_30 -# 650| v0_33(void) = NoOp : -# 642| v0_34(void) = ReturnVoid : -# 642| v0_35(void) = UnmodeledUse : mu* -# 642| v0_36(void) = AliasedUse : ~mu0_2 -# 642| v0_37(void) = ExitFunction : +# 644| r0_10(glval) = CopyValue : r0_9 +# 644| r0_11(glval) = FieldAddress[m_a] : r0_10 +# 644| mu0_12(int) = Store : &:r0_11, r0_8 +# 645| r0_13(int) = Constant[2] : +#-----| r0_14(C *) = CopyValue : r0_3 +# 645| r0_15(glval) = FieldAddress[m_a] : r0_14 +# 645| mu0_16(int) = Store : &:r0_15, r0_13 +# 646| r0_17(glval) = VariableAddress[x] : +# 646| mu0_18(int) = Uninitialized[x] : &:r0_17 +# 647| r0_19(C *) = CopyValue : r0_3 +# 647| r0_20(glval) = FieldAddress[m_a] : r0_19 +# 647| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 647| r0_22(glval) = VariableAddress[x] : +# 647| mu0_23(int) = Store : &:r0_22, r0_21 +# 648| r0_24(C *) = CopyValue : r0_3 +# 648| r0_25(glval) = CopyValue : r0_24 +# 648| r0_26(glval) = FieldAddress[m_a] : r0_25 +# 648| r0_27(int) = Load : &:r0_26, ~mu0_2 +# 648| r0_28(glval) = VariableAddress[x] : +# 648| mu0_29(int) = Store : &:r0_28, r0_27 +#-----| r0_30(C *) = CopyValue : r0_3 +# 649| r0_31(glval) = FieldAddress[m_a] : r0_30 +# 649| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 649| r0_33(glval) = VariableAddress[x] : +# 649| mu0_34(int) = Store : &:r0_33, r0_32 +# 650| v0_35(void) = NoOp : +# 642| v0_36(void) = ReturnVoid : +# 642| v0_37(void) = UnmodeledUse : mu* +# 642| v0_38(void) = AliasedUse : ~mu0_2 +# 642| v0_39(void) = ExitFunction : # 652| void C::MethodCalls() # 652| Block 0 @@ -2955,24 +2999,25 @@ ir.cpp: # 653| v0_9(void) = ^BufferReadSideEffect[-1] : &:r0_4, ~mu0_2 # 653| mu0_10(C) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 654| r0_11(C *) = CopyValue : r0_3 -# 654| r0_12(glval) = FunctionAddress[InstanceMemberFunction] : -# 654| r0_13(int) = Constant[1] : -# 654| r0_14(int) = Call : func:r0_12, this:r0_11, 0:r0_13 -# 654| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 654| v0_16(void) = ^BufferReadSideEffect[-1] : &:r0_11, ~mu0_2 -# 654| mu0_17(C) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -#-----| r0_18(C *) = CopyValue : r0_3 -# 655| r0_19(glval) = FunctionAddress[InstanceMemberFunction] : -# 655| r0_20(int) = Constant[2] : -# 655| r0_21(int) = Call : func:r0_19, this:r0_18, 0:r0_20 -# 655| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_23(void) = ^BufferReadSideEffect[-1] : &:r0_18, ~mu0_2 -#-----| mu0_24(C) = ^IndirectMayWriteSideEffect[-1] : &:r0_18 -# 656| v0_25(void) = NoOp : -# 652| v0_26(void) = ReturnVoid : -# 652| v0_27(void) = UnmodeledUse : mu* -# 652| v0_28(void) = AliasedUse : ~mu0_2 -# 652| v0_29(void) = ExitFunction : +# 654| r0_12(glval) = CopyValue : r0_11 +# 654| r0_13(glval) = FunctionAddress[InstanceMemberFunction] : +# 654| r0_14(int) = Constant[1] : +# 654| r0_15(int) = Call : func:r0_13, this:r0_12, 0:r0_14 +# 654| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +# 654| v0_17(void) = ^BufferReadSideEffect[-1] : &:r0_12, ~mu0_2 +# 654| mu0_18(C) = ^IndirectMayWriteSideEffect[-1] : &:r0_12 +#-----| r0_19(C *) = CopyValue : r0_3 +# 655| r0_20(glval) = FunctionAddress[InstanceMemberFunction] : +# 655| r0_21(int) = Constant[2] : +# 655| r0_22(int) = Call : func:r0_20, this:r0_19, 0:r0_21 +# 655| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_24(void) = ^BufferReadSideEffect[-1] : &:r0_19, ~mu0_2 +#-----| mu0_25(C) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 +# 656| v0_26(void) = NoOp : +# 652| v0_27(void) = ReturnVoid : +# 652| v0_28(void) = UnmodeledUse : mu* +# 652| v0_29(void) = AliasedUse : ~mu0_2 +# 652| v0_30(void) = ExitFunction : # 658| void C::C() # 658| Block 0 @@ -3032,12 +3077,13 @@ ir.cpp: # 679| mu0_2(unknown) = UnmodeledDefinition : # 680| r0_3(glval) = VariableAddress[#return] : # 680| r0_4(glval) = VariableAddress[g] : -# 680| mu0_5(int &) = Store : &:r0_3, r0_4 -# 679| r0_6(glval) = VariableAddress[#return] : -# 679| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 679| v0_8(void) = UnmodeledUse : mu* -# 679| v0_9(void) = AliasedUse : ~mu0_2 -# 679| v0_10(void) = ExitFunction : +# 680| r0_5(int &) = CopyValue : r0_4 +# 680| mu0_6(int &) = Store : &:r0_3, r0_5 +# 679| r0_7(glval) = VariableAddress[#return] : +# 679| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 679| v0_9(void) = UnmodeledUse : mu* +# 679| v0_10(void) = AliasedUse : ~mu0_2 +# 679| v0_11(void) = ExitFunction : # 685| void InitReference(int) # 685| Block 0 @@ -3048,46 +3094,53 @@ ir.cpp: # 685| mu0_4(int) = InitializeParameter[x] : &:r0_3 # 686| r0_5(glval) = VariableAddress[r] : # 686| r0_6(glval) = VariableAddress[x] : -# 686| mu0_7(int &) = Store : &:r0_5, r0_6 -# 687| r0_8(glval) = VariableAddress[r2] : -# 687| r0_9(glval) = VariableAddress[r] : -# 687| r0_10(int &) = Load : &:r0_9, ~mu0_2 -# 687| mu0_11(int &) = Store : &:r0_8, r0_10 -# 688| r0_12(glval) = VariableAddress[r3] : -# 688| r0_13(glval) = FunctionAddress[ReturnReference] : -# 688| r0_14(String &) = Call : func:r0_13 -# 688| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 688| r0_16(glval) = Convert : r0_14 -# 688| mu0_17(String &) = Store : &:r0_12, r0_16 -# 689| v0_18(void) = NoOp : -# 685| v0_19(void) = ReturnVoid : -# 685| v0_20(void) = UnmodeledUse : mu* -# 685| v0_21(void) = AliasedUse : ~mu0_2 -# 685| v0_22(void) = ExitFunction : +# 686| r0_7(int &) = CopyValue : r0_6 +# 686| mu0_8(int &) = Store : &:r0_5, r0_7 +# 687| r0_9(glval) = VariableAddress[r2] : +# 687| r0_10(glval) = VariableAddress[r] : +# 687| r0_11(int &) = Load : &:r0_10, ~mu0_2 +# 687| r0_12(glval) = CopyValue : r0_11 +# 687| r0_13(int &) = CopyValue : r0_12 +# 687| mu0_14(int &) = Store : &:r0_9, r0_13 +# 688| r0_15(glval) = VariableAddress[r3] : +# 688| r0_16(glval) = FunctionAddress[ReturnReference] : +# 688| r0_17(String &) = Call : func:r0_16 +# 688| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 688| r0_19(glval) = CopyValue : r0_17 +# 688| r0_20(glval) = Convert : r0_19 +# 688| r0_21(String &) = CopyValue : r0_20 +# 688| mu0_22(String &) = Store : &:r0_15, r0_21 +# 689| v0_23(void) = NoOp : +# 685| v0_24(void) = ReturnVoid : +# 685| v0_25(void) = UnmodeledUse : mu* +# 685| v0_26(void) = AliasedUse : ~mu0_2 +# 685| v0_27(void) = ExitFunction : # 691| void ArrayReferences() # 691| Block 0 -# 691| v0_0(void) = EnterFunction : -# 691| mu0_1(unknown) = AliasedDefinition : -# 691| mu0_2(unknown) = UnmodeledDefinition : -# 692| r0_3(glval) = VariableAddress[a] : -# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 -# 693| r0_5(glval) = VariableAddress[ra] : -# 693| r0_6(glval) = VariableAddress[a] : -# 693| mu0_7(int(&)[10]) = Store : &:r0_5, r0_6 -# 694| r0_8(glval) = VariableAddress[x] : -# 694| r0_9(glval) = VariableAddress[ra] : -# 694| r0_10(int(&)[10]) = Load : &:r0_9, ~mu0_2 -# 694| r0_11(int *) = Convert : r0_10 -# 694| r0_12(int) = Constant[5] : -# 694| r0_13(glval) = PointerAdd[4] : r0_11, r0_12 -# 694| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 694| mu0_15(int) = Store : &:r0_8, r0_14 -# 695| v0_16(void) = NoOp : -# 691| v0_17(void) = ReturnVoid : -# 691| v0_18(void) = UnmodeledUse : mu* -# 691| v0_19(void) = AliasedUse : ~mu0_2 -# 691| v0_20(void) = ExitFunction : +# 691| v0_0(void) = EnterFunction : +# 691| mu0_1(unknown) = AliasedDefinition : +# 691| mu0_2(unknown) = UnmodeledDefinition : +# 692| r0_3(glval) = VariableAddress[a] : +# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 +# 693| r0_5(glval) = VariableAddress[ra] : +# 693| r0_6(glval) = VariableAddress[a] : +# 693| r0_7(int(&)[10]) = CopyValue : r0_6 +# 693| mu0_8(int(&)[10]) = Store : &:r0_5, r0_7 +# 694| r0_9(glval) = VariableAddress[x] : +# 694| r0_10(glval) = VariableAddress[ra] : +# 694| r0_11(int(&)[10]) = Load : &:r0_10, ~mu0_2 +# 694| r0_12(glval) = CopyValue : r0_11 +# 694| r0_13(int *) = Convert : r0_12 +# 694| r0_14(int) = Constant[5] : +# 694| r0_15(glval) = PointerAdd[4] : r0_13, r0_14 +# 694| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 694| mu0_17(int) = Store : &:r0_9, r0_16 +# 695| v0_18(void) = NoOp : +# 691| v0_19(void) = ReturnVoid : +# 691| v0_20(void) = UnmodeledUse : mu* +# 691| v0_21(void) = AliasedUse : ~mu0_2 +# 691| v0_22(void) = ExitFunction : # 697| void FunctionReferences() # 697| Block 0 @@ -3096,21 +3149,24 @@ ir.cpp: # 697| mu0_2(unknown) = UnmodeledDefinition : # 698| r0_3(glval<..(&)(..)>) = VariableAddress[rfn] : # 698| r0_4(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 698| mu0_5(..(&)(..)) = Store : &:r0_3, r0_4 -# 699| r0_6(glval<..(*)(..)>) = VariableAddress[pfn] : -# 699| r0_7(glval<..(&)(..)>) = VariableAddress[rfn] : -# 699| r0_8(..(&)(..)) = Load : &:r0_7, ~mu0_2 -# 699| mu0_9(..(*)(..)) = Store : &:r0_6, r0_8 -# 700| r0_10(glval<..(&)(..)>) = VariableAddress[rfn] : -# 700| r0_11(..(&)(..)) = Load : &:r0_10, ~mu0_2 -# 700| r0_12(int) = Constant[5] : -# 700| r0_13(int) = Call : func:r0_11, 0:r0_12 -# 700| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 701| v0_15(void) = NoOp : -# 697| v0_16(void) = ReturnVoid : -# 697| v0_17(void) = UnmodeledUse : mu* -# 697| v0_18(void) = AliasedUse : ~mu0_2 -# 697| v0_19(void) = ExitFunction : +# 698| r0_5(..(&)(..)) = CopyValue : r0_4 +# 698| mu0_6(..(&)(..)) = Store : &:r0_3, r0_5 +# 699| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : +# 699| r0_8(glval<..(&)(..)>) = VariableAddress[rfn] : +# 699| r0_9(..(&)(..)) = Load : &:r0_8, ~mu0_2 +# 699| r0_10(..(*)(..)) = CopyValue : r0_9 +# 699| mu0_11(..(*)(..)) = Store : &:r0_7, r0_10 +# 700| r0_12(glval<..(&)(..)>) = VariableAddress[rfn] : +# 700| r0_13(..(&)(..)) = Load : &:r0_12, ~mu0_2 +# 700| r0_14(..(*)(..)) = CopyValue : r0_13 +# 700| r0_15(int) = Constant[5] : +# 700| r0_16(int) = Call : func:r0_14, 0:r0_15 +# 700| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 701| v0_18(void) = NoOp : +# 697| v0_19(void) = ReturnVoid : +# 697| v0_20(void) = UnmodeledUse : mu* +# 697| v0_21(void) = AliasedUse : ~mu0_2 +# 697| v0_22(void) = ExitFunction : # 704| int min(int, int) # 704| Block 0 @@ -3345,24 +3401,30 @@ ir.cpp: #-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 #-----| r0_6(Base *) = CopyValue : r0_3 #-----| r0_7(glval) = FieldAddress[base_s] : r0_6 -# 745| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Base &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = FieldAddress[base_s] : r0_10 -# 745| r0_12(String &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 745| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(glval) = VariableAddress[#return] : -#-----| r0_19(Base *) = CopyValue : r0_3 -#-----| mu0_20(Base &) = Store : &:r0_18, r0_19 -# 745| r0_21(glval) = VariableAddress[#return] : -# 745| v0_22(void) = ReturnValue : &:r0_21, ~mu0_2 -# 745| v0_23(void) = UnmodeledUse : mu* -# 745| v0_24(void) = AliasedUse : ~mu0_2 -# 745| v0_25(void) = ExitFunction : +#-----| r0_8(String *) = CopyValue : r0_7 +# 745| r0_9(glval) = FunctionAddress[operator=] : +#-----| r0_10(glval) = VariableAddress[p#0] : +#-----| r0_11(Base &) = Load : &:r0_10, ~mu0_2 +#-----| r0_12(glval) = CopyValue : r0_11 +#-----| r0_13(glval) = FieldAddress[base_s] : r0_12 +#-----| r0_14(String &) = CopyValue : r0_13 +# 745| r0_15(String &) = Call : func:r0_9, this:r0_8, 0:r0_14 +# 745| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_17(void) = ^BufferReadSideEffect[-1] : &:r0_8, ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[0] : &:r0_14, ~mu0_2 +#-----| mu0_19(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 +#-----| mu0_20(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_14 +#-----| r0_21(glval) = CopyValue : r0_15 +#-----| r0_22(glval) = VariableAddress[#return] : +#-----| r0_23(Base *) = CopyValue : r0_3 +#-----| r0_24(glval) = CopyValue : r0_23 +#-----| r0_25(Base &) = CopyValue : r0_24 +#-----| mu0_26(Base &) = Store : &:r0_22, r0_25 +# 745| r0_27(glval) = VariableAddress[#return] : +# 745| v0_28(void) = ReturnValue : &:r0_27, ~mu0_2 +# 745| v0_29(void) = UnmodeledUse : mu* +# 745| v0_30(void) = AliasedUse : ~mu0_2 +# 745| v0_31(void) = ExitFunction : # 745| void Base::Base(Base const&) # 745| Block 0 @@ -3416,557 +3478,606 @@ ir.cpp: # 754| Middle& Middle::operator=(Middle const&) # 754| Block 0 -# 754| v0_0(void) = EnterFunction : -# 754| mu0_1(unknown) = AliasedDefinition : -# 754| mu0_2(unknown) = UnmodeledDefinition : -# 754| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Middle &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Middle *) = CopyValue : r0_3 -#-----| r0_7(Base *) = ConvertToBase[Middle : Base] : r0_6 -# 754| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Base *) = ConvertToBase[Middle : Base] : r0_10 -# 754| r0_12(Base &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 754| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(Middle *) = CopyValue : r0_3 -#-----| r0_19(glval) = FieldAddress[middle_s] : r0_18 -# 754| r0_20(glval) = FunctionAddress[operator=] : -#-----| r0_21(glval) = VariableAddress[p#0] : -#-----| r0_22(Middle &) = Load : &:r0_21, ~mu0_2 -#-----| r0_23(glval) = FieldAddress[middle_s] : r0_22 -# 754| r0_24(String &) = Call : func:r0_20, this:r0_19, 0:r0_23 -# 754| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_26(void) = ^BufferReadSideEffect[-1] : &:r0_19, ~mu0_2 -#-----| v0_27(void) = ^BufferReadSideEffect[0] : &:r0_23, ~mu0_2 -#-----| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -#-----| mu0_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -#-----| r0_30(glval) = VariableAddress[#return] : -#-----| r0_31(Middle *) = CopyValue : r0_3 -#-----| mu0_32(Middle &) = Store : &:r0_30, r0_31 -# 754| r0_33(glval) = VariableAddress[#return] : -# 754| v0_34(void) = ReturnValue : &:r0_33, ~mu0_2 -# 754| v0_35(void) = UnmodeledUse : mu* -# 754| v0_36(void) = AliasedUse : ~mu0_2 -# 754| v0_37(void) = ExitFunction : +# 754| v0_0(void) = EnterFunction : +# 754| mu0_1(unknown) = AliasedDefinition : +# 754| mu0_2(unknown) = UnmodeledDefinition : +# 754| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Middle &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Middle *) = CopyValue : r0_3 +#-----| r0_7(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_6 +# 754| r0_8(glval) = FunctionAddress[operator=] : +#-----| r0_9(glval) = VariableAddress[p#0] : +#-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Middle *) = CopyValue : r0_11 +#-----| r0_13(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Base &) = CopyValue : r0_14 +# 754| r0_16(Base &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 754| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 +#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 +#-----| mu0_20(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 +#-----| r0_22(glval) = CopyValue : r0_16 +#-----| r0_23(Middle *) = CopyValue : r0_3 +#-----| r0_24(glval) = FieldAddress[middle_s] : r0_23 +#-----| r0_25(String *) = CopyValue : r0_24 +# 754| r0_26(glval) = FunctionAddress[operator=] : +#-----| r0_27(glval) = VariableAddress[p#0] : +#-----| r0_28(Middle &) = Load : &:r0_27, ~mu0_2 +#-----| r0_29(glval) = CopyValue : r0_28 +#-----| r0_30(glval) = FieldAddress[middle_s] : r0_29 +#-----| r0_31(String &) = CopyValue : r0_30 +# 754| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 +# 754| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 +#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +#-----| r0_38(glval) = CopyValue : r0_32 +#-----| r0_39(glval) = VariableAddress[#return] : +#-----| r0_40(Middle *) = CopyValue : r0_3 +#-----| r0_41(glval) = CopyValue : r0_40 +#-----| r0_42(Middle &) = CopyValue : r0_41 +#-----| mu0_43(Middle &) = Store : &:r0_39, r0_42 +# 754| r0_44(glval) = VariableAddress[#return] : +# 754| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 +# 754| v0_46(void) = UnmodeledUse : mu* +# 754| v0_47(void) = AliasedUse : ~mu0_2 +# 754| v0_48(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 -# 757| v0_0(void) = EnterFunction : -# 757| mu0_1(unknown) = AliasedDefinition : -# 757| mu0_2(unknown) = UnmodeledDefinition : -# 757| r0_3(glval) = InitializeThis : -# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 -# 757| r0_5(glval) = FunctionAddress[Base] : -# 757| v0_6(void) = Call : func:r0_5, this:r0_4 -# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 757| r0_8(glval) = FieldAddress[middle_s] : r0_3 -# 757| r0_9(glval) = FunctionAddress[String] : -# 757| v0_10(void) = Call : func:r0_9, this:r0_8 -# 757| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 758| v0_12(void) = NoOp : -# 757| v0_13(void) = ReturnVoid : -# 757| v0_14(void) = UnmodeledUse : mu* -# 757| v0_15(void) = AliasedUse : ~mu0_2 -# 757| v0_16(void) = ExitFunction : +# 757| v0_0(void) = EnterFunction : +# 757| mu0_1(unknown) = AliasedDefinition : +# 757| mu0_2(unknown) = UnmodeledDefinition : +# 757| r0_3(glval) = InitializeThis : +# 757| r0_4(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_3 +# 757| r0_5(glval) = FunctionAddress[Base] : +# 757| v0_6(void) = Call : func:r0_5, this:r0_4 +# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 757| r0_8(glval) = FieldAddress[middle_s] : r0_3 +# 757| r0_9(glval) = FunctionAddress[String] : +# 757| v0_10(void) = Call : func:r0_9, this:r0_8 +# 757| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 758| v0_12(void) = NoOp : +# 757| v0_13(void) = ReturnVoid : +# 757| v0_14(void) = UnmodeledUse : mu* +# 757| v0_15(void) = AliasedUse : ~mu0_2 +# 757| v0_16(void) = ExitFunction : # 759| void Middle::~Middle() # 759| Block 0 -# 759| v0_0(void) = EnterFunction : -# 759| mu0_1(unknown) = AliasedDefinition : -# 759| mu0_2(unknown) = UnmodeledDefinition : -# 759| r0_3(glval) = InitializeThis : -# 760| v0_4(void) = NoOp : -# 760| r0_5(glval) = FieldAddress[middle_s] : r0_3 -# 760| r0_6(glval) = FunctionAddress[~String] : -# 760| v0_7(void) = Call : func:r0_6, this:r0_5 -# 760| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 760| r0_9(glval) = ConvertToBase[Middle : Base] : r0_3 -# 760| r0_10(glval) = FunctionAddress[~Base] : -# 760| v0_11(void) = Call : func:r0_10, this:r0_9 -# 760| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 759| v0_13(void) = ReturnVoid : -# 759| v0_14(void) = UnmodeledUse : mu* -# 759| v0_15(void) = AliasedUse : ~mu0_2 -# 759| v0_16(void) = ExitFunction : +# 759| v0_0(void) = EnterFunction : +# 759| mu0_1(unknown) = AliasedDefinition : +# 759| mu0_2(unknown) = UnmodeledDefinition : +# 759| r0_3(glval) = InitializeThis : +# 760| v0_4(void) = NoOp : +# 760| r0_5(glval) = FieldAddress[middle_s] : r0_3 +# 760| r0_6(glval) = FunctionAddress[~String] : +# 760| v0_7(void) = Call : func:r0_6, this:r0_5 +# 760| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 760| r0_9(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_3 +# 760| r0_10(glval) = FunctionAddress[~Base] : +# 760| v0_11(void) = Call : func:r0_10, this:r0_9 +# 760| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 759| v0_13(void) = ReturnVoid : +# 759| v0_14(void) = UnmodeledUse : mu* +# 759| v0_15(void) = AliasedUse : ~mu0_2 +# 759| v0_16(void) = ExitFunction : # 763| Derived& Derived::operator=(Derived const&) # 763| Block 0 -# 763| v0_0(void) = EnterFunction : -# 763| mu0_1(unknown) = AliasedDefinition : -# 763| mu0_2(unknown) = UnmodeledDefinition : -# 763| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Derived &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Derived *) = CopyValue : r0_3 -#-----| r0_7(Middle *) = ConvertToBase[Derived : Middle] : r0_6 -# 763| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Middle *) = ConvertToBase[Derived : Middle] : r0_10 -# 763| r0_12(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 763| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(Derived *) = CopyValue : r0_3 -#-----| r0_19(glval) = FieldAddress[derived_s] : r0_18 -# 763| r0_20(glval) = FunctionAddress[operator=] : -#-----| r0_21(glval) = VariableAddress[p#0] : -#-----| r0_22(Derived &) = Load : &:r0_21, ~mu0_2 -#-----| r0_23(glval) = FieldAddress[derived_s] : r0_22 -# 763| r0_24(String &) = Call : func:r0_20, this:r0_19, 0:r0_23 -# 763| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_26(void) = ^BufferReadSideEffect[-1] : &:r0_19, ~mu0_2 -#-----| v0_27(void) = ^BufferReadSideEffect[0] : &:r0_23, ~mu0_2 -#-----| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -#-----| mu0_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -#-----| r0_30(glval) = VariableAddress[#return] : -#-----| r0_31(Derived *) = CopyValue : r0_3 -#-----| mu0_32(Derived &) = Store : &:r0_30, r0_31 -# 763| r0_33(glval) = VariableAddress[#return] : -# 763| v0_34(void) = ReturnValue : &:r0_33, ~mu0_2 -# 763| v0_35(void) = UnmodeledUse : mu* -# 763| v0_36(void) = AliasedUse : ~mu0_2 -# 763| v0_37(void) = ExitFunction : +# 763| v0_0(void) = EnterFunction : +# 763| mu0_1(unknown) = AliasedDefinition : +# 763| mu0_2(unknown) = UnmodeledDefinition : +# 763| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Derived &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Derived *) = CopyValue : r0_3 +#-----| r0_7(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_6 +# 763| r0_8(glval) = FunctionAddress[operator=] : +#-----| r0_9(glval) = VariableAddress[p#0] : +#-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Derived *) = CopyValue : r0_11 +#-----| r0_13(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Middle &) = CopyValue : r0_14 +# 763| r0_16(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 763| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_7, ~mu0_2 +#-----| v0_19(void) = ^BufferReadSideEffect[0] : &:r0_15, ~mu0_2 +#-----| mu0_20(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +#-----| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_15 +#-----| r0_22(glval) = CopyValue : r0_16 +#-----| r0_23(Derived *) = CopyValue : r0_3 +#-----| r0_24(glval) = FieldAddress[derived_s] : r0_23 +#-----| r0_25(String *) = CopyValue : r0_24 +# 763| r0_26(glval) = FunctionAddress[operator=] : +#-----| r0_27(glval) = VariableAddress[p#0] : +#-----| r0_28(Derived &) = Load : &:r0_27, ~mu0_2 +#-----| r0_29(glval) = CopyValue : r0_28 +#-----| r0_30(glval) = FieldAddress[derived_s] : r0_29 +#-----| r0_31(String &) = CopyValue : r0_30 +# 763| r0_32(String &) = Call : func:r0_26, this:r0_25, 0:r0_31 +# 763| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_25, ~mu0_2 +#-----| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +#-----| mu0_36(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +#-----| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +#-----| r0_38(glval) = CopyValue : r0_32 +#-----| r0_39(glval) = VariableAddress[#return] : +#-----| r0_40(Derived *) = CopyValue : r0_3 +#-----| r0_41(glval) = CopyValue : r0_40 +#-----| r0_42(Derived &) = CopyValue : r0_41 +#-----| mu0_43(Derived &) = Store : &:r0_39, r0_42 +# 763| r0_44(glval) = VariableAddress[#return] : +# 763| v0_45(void) = ReturnValue : &:r0_44, ~mu0_2 +# 763| v0_46(void) = UnmodeledUse : mu* +# 763| v0_47(void) = AliasedUse : ~mu0_2 +# 763| v0_48(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 -# 766| v0_0(void) = EnterFunction : -# 766| mu0_1(unknown) = AliasedDefinition : -# 766| mu0_2(unknown) = UnmodeledDefinition : -# 766| r0_3(glval) = InitializeThis : -# 766| r0_4(glval) = ConvertToBase[Derived : Middle] : r0_3 -# 766| r0_5(glval) = FunctionAddress[Middle] : -# 766| v0_6(void) = Call : func:r0_5, this:r0_4 -# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 766| r0_8(glval) = FieldAddress[derived_s] : r0_3 -# 766| r0_9(glval) = FunctionAddress[String] : -# 766| v0_10(void) = Call : func:r0_9, this:r0_8 -# 766| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 767| v0_12(void) = NoOp : -# 766| v0_13(void) = ReturnVoid : -# 766| v0_14(void) = UnmodeledUse : mu* -# 766| v0_15(void) = AliasedUse : ~mu0_2 -# 766| v0_16(void) = ExitFunction : +# 766| v0_0(void) = EnterFunction : +# 766| mu0_1(unknown) = AliasedDefinition : +# 766| mu0_2(unknown) = UnmodeledDefinition : +# 766| r0_3(glval) = InitializeThis : +# 766| r0_4(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_3 +# 766| r0_5(glval) = FunctionAddress[Middle] : +# 766| v0_6(void) = Call : func:r0_5, this:r0_4 +# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 766| r0_8(glval) = FieldAddress[derived_s] : r0_3 +# 766| r0_9(glval) = FunctionAddress[String] : +# 766| v0_10(void) = Call : func:r0_9, this:r0_8 +# 766| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 767| v0_12(void) = NoOp : +# 766| v0_13(void) = ReturnVoid : +# 766| v0_14(void) = UnmodeledUse : mu* +# 766| v0_15(void) = AliasedUse : ~mu0_2 +# 766| v0_16(void) = ExitFunction : # 768| void Derived::~Derived() # 768| Block 0 -# 768| v0_0(void) = EnterFunction : -# 768| mu0_1(unknown) = AliasedDefinition : -# 768| mu0_2(unknown) = UnmodeledDefinition : -# 768| r0_3(glval) = InitializeThis : -# 769| v0_4(void) = NoOp : -# 769| r0_5(glval) = FieldAddress[derived_s] : r0_3 -# 769| r0_6(glval) = FunctionAddress[~String] : -# 769| v0_7(void) = Call : func:r0_6, this:r0_5 -# 769| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 769| r0_9(glval) = ConvertToBase[Derived : Middle] : r0_3 -# 769| r0_10(glval) = FunctionAddress[~Middle] : -# 769| v0_11(void) = Call : func:r0_10, this:r0_9 -# 769| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 768| v0_13(void) = ReturnVoid : -# 768| v0_14(void) = UnmodeledUse : mu* -# 768| v0_15(void) = AliasedUse : ~mu0_2 -# 768| v0_16(void) = ExitFunction : +# 768| v0_0(void) = EnterFunction : +# 768| mu0_1(unknown) = AliasedDefinition : +# 768| mu0_2(unknown) = UnmodeledDefinition : +# 768| r0_3(glval) = InitializeThis : +# 769| v0_4(void) = NoOp : +# 769| r0_5(glval) = FieldAddress[derived_s] : r0_3 +# 769| r0_6(glval) = FunctionAddress[~String] : +# 769| v0_7(void) = Call : func:r0_6, this:r0_5 +# 769| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 769| r0_9(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_3 +# 769| r0_10(glval) = FunctionAddress[~Middle] : +# 769| v0_11(void) = Call : func:r0_10, this:r0_9 +# 769| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 768| v0_13(void) = ReturnVoid : +# 768| v0_14(void) = UnmodeledUse : mu* +# 768| v0_15(void) = AliasedUse : ~mu0_2 +# 768| v0_16(void) = ExitFunction : # 775| void MiddleVB1::MiddleVB1() # 775| Block 0 -# 775| v0_0(void) = EnterFunction : -# 775| mu0_1(unknown) = AliasedDefinition : -# 775| mu0_2(unknown) = UnmodeledDefinition : -# 775| r0_3(glval) = InitializeThis : -# 775| r0_4(glval) = ConvertToBase[MiddleVB1 : Base] : r0_3 -# 775| r0_5(glval) = FunctionAddress[Base] : -# 775| v0_6(void) = Call : func:r0_5, this:r0_4 -# 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 775| r0_8(glval) = FieldAddress[middlevb1_s] : r0_3 -# 775| r0_9(glval) = FunctionAddress[String] : -# 775| v0_10(void) = Call : func:r0_9, this:r0_8 -# 775| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 776| v0_12(void) = NoOp : -# 775| v0_13(void) = ReturnVoid : -# 775| v0_14(void) = UnmodeledUse : mu* -# 775| v0_15(void) = AliasedUse : ~mu0_2 -# 775| v0_16(void) = ExitFunction : +# 775| v0_0(void) = EnterFunction : +# 775| mu0_1(unknown) = AliasedDefinition : +# 775| mu0_2(unknown) = UnmodeledDefinition : +# 775| r0_3(glval) = InitializeThis : +# 775| r0_4(glval) = ConvertToNonVirtualBase[MiddleVB1 : Base] : r0_3 +# 775| r0_5(glval) = FunctionAddress[Base] : +# 775| v0_6(void) = Call : func:r0_5, this:r0_4 +# 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 775| r0_8(glval) = FieldAddress[middlevb1_s] : r0_3 +# 775| r0_9(glval) = FunctionAddress[String] : +# 775| v0_10(void) = Call : func:r0_9, this:r0_8 +# 775| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 776| v0_12(void) = NoOp : +# 775| v0_13(void) = ReturnVoid : +# 775| v0_14(void) = UnmodeledUse : mu* +# 775| v0_15(void) = AliasedUse : ~mu0_2 +# 775| v0_16(void) = ExitFunction : # 777| void MiddleVB1::~MiddleVB1() # 777| Block 0 -# 777| v0_0(void) = EnterFunction : -# 777| mu0_1(unknown) = AliasedDefinition : -# 777| mu0_2(unknown) = UnmodeledDefinition : -# 777| r0_3(glval) = InitializeThis : -# 778| v0_4(void) = NoOp : -# 778| r0_5(glval) = FieldAddress[middlevb1_s] : r0_3 -# 778| r0_6(glval) = FunctionAddress[~String] : -# 778| v0_7(void) = Call : func:r0_6, this:r0_5 -# 778| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 778| r0_9(glval) = ConvertToBase[MiddleVB1 : Base] : r0_3 -# 778| r0_10(glval) = FunctionAddress[~Base] : -# 778| v0_11(void) = Call : func:r0_10, this:r0_9 -# 778| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 777| v0_13(void) = ReturnVoid : -# 777| v0_14(void) = UnmodeledUse : mu* -# 777| v0_15(void) = AliasedUse : ~mu0_2 -# 777| v0_16(void) = ExitFunction : +# 777| v0_0(void) = EnterFunction : +# 777| mu0_1(unknown) = AliasedDefinition : +# 777| mu0_2(unknown) = UnmodeledDefinition : +# 777| r0_3(glval) = InitializeThis : +# 778| v0_4(void) = NoOp : +# 778| r0_5(glval) = FieldAddress[middlevb1_s] : r0_3 +# 778| r0_6(glval) = FunctionAddress[~String] : +# 778| v0_7(void) = Call : func:r0_6, this:r0_5 +# 778| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 778| r0_9(glval) = ConvertToNonVirtualBase[MiddleVB1 : Base] : r0_3 +# 778| r0_10(glval) = FunctionAddress[~Base] : +# 778| v0_11(void) = Call : func:r0_10, this:r0_9 +# 778| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 777| v0_13(void) = ReturnVoid : +# 777| v0_14(void) = UnmodeledUse : mu* +# 777| v0_15(void) = AliasedUse : ~mu0_2 +# 777| v0_16(void) = ExitFunction : # 784| void MiddleVB2::MiddleVB2() # 784| Block 0 -# 784| v0_0(void) = EnterFunction : -# 784| mu0_1(unknown) = AliasedDefinition : -# 784| mu0_2(unknown) = UnmodeledDefinition : -# 784| r0_3(glval) = InitializeThis : -# 784| r0_4(glval) = ConvertToBase[MiddleVB2 : Base] : r0_3 -# 784| r0_5(glval) = FunctionAddress[Base] : -# 784| v0_6(void) = Call : func:r0_5, this:r0_4 -# 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 784| r0_8(glval) = FieldAddress[middlevb2_s] : r0_3 -# 784| r0_9(glval) = FunctionAddress[String] : -# 784| v0_10(void) = Call : func:r0_9, this:r0_8 -# 784| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 785| v0_12(void) = NoOp : -# 784| v0_13(void) = ReturnVoid : -# 784| v0_14(void) = UnmodeledUse : mu* -# 784| v0_15(void) = AliasedUse : ~mu0_2 -# 784| v0_16(void) = ExitFunction : +# 784| v0_0(void) = EnterFunction : +# 784| mu0_1(unknown) = AliasedDefinition : +# 784| mu0_2(unknown) = UnmodeledDefinition : +# 784| r0_3(glval) = InitializeThis : +# 784| r0_4(glval) = ConvertToNonVirtualBase[MiddleVB2 : Base] : r0_3 +# 784| r0_5(glval) = FunctionAddress[Base] : +# 784| v0_6(void) = Call : func:r0_5, this:r0_4 +# 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 784| r0_8(glval) = FieldAddress[middlevb2_s] : r0_3 +# 784| r0_9(glval) = FunctionAddress[String] : +# 784| v0_10(void) = Call : func:r0_9, this:r0_8 +# 784| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 785| v0_12(void) = NoOp : +# 784| v0_13(void) = ReturnVoid : +# 784| v0_14(void) = UnmodeledUse : mu* +# 784| v0_15(void) = AliasedUse : ~mu0_2 +# 784| v0_16(void) = ExitFunction : # 786| void MiddleVB2::~MiddleVB2() # 786| Block 0 -# 786| v0_0(void) = EnterFunction : -# 786| mu0_1(unknown) = AliasedDefinition : -# 786| mu0_2(unknown) = UnmodeledDefinition : -# 786| r0_3(glval) = InitializeThis : -# 787| v0_4(void) = NoOp : -# 787| r0_5(glval) = FieldAddress[middlevb2_s] : r0_3 -# 787| r0_6(glval) = FunctionAddress[~String] : -# 787| v0_7(void) = Call : func:r0_6, this:r0_5 -# 787| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 787| r0_9(glval) = ConvertToBase[MiddleVB2 : Base] : r0_3 -# 787| r0_10(glval) = FunctionAddress[~Base] : -# 787| v0_11(void) = Call : func:r0_10, this:r0_9 -# 787| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 786| v0_13(void) = ReturnVoid : -# 786| v0_14(void) = UnmodeledUse : mu* -# 786| v0_15(void) = AliasedUse : ~mu0_2 -# 786| v0_16(void) = ExitFunction : +# 786| v0_0(void) = EnterFunction : +# 786| mu0_1(unknown) = AliasedDefinition : +# 786| mu0_2(unknown) = UnmodeledDefinition : +# 786| r0_3(glval) = InitializeThis : +# 787| v0_4(void) = NoOp : +# 787| r0_5(glval) = FieldAddress[middlevb2_s] : r0_3 +# 787| r0_6(glval) = FunctionAddress[~String] : +# 787| v0_7(void) = Call : func:r0_6, this:r0_5 +# 787| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 787| r0_9(glval) = ConvertToNonVirtualBase[MiddleVB2 : Base] : r0_3 +# 787| r0_10(glval) = FunctionAddress[~Base] : +# 787| v0_11(void) = Call : func:r0_10, this:r0_9 +# 787| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 786| v0_13(void) = ReturnVoid : +# 786| v0_14(void) = UnmodeledUse : mu* +# 786| v0_15(void) = AliasedUse : ~mu0_2 +# 786| v0_16(void) = ExitFunction : # 793| void DerivedVB::DerivedVB() # 793| Block 0 -# 793| v0_0(void) = EnterFunction : -# 793| mu0_1(unknown) = AliasedDefinition : -# 793| mu0_2(unknown) = UnmodeledDefinition : -# 793| r0_3(glval) = InitializeThis : -# 793| r0_4(glval) = ConvertToBase[DerivedVB : Base] : r0_3 -# 793| r0_5(glval) = FunctionAddress[Base] : -# 793| v0_6(void) = Call : func:r0_5, this:r0_4 -# 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_8(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 -# 793| r0_9(glval) = FunctionAddress[MiddleVB1] : -# 793| v0_10(void) = Call : func:r0_9, this:r0_8 -# 793| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_12(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 -# 793| r0_13(glval) = FunctionAddress[MiddleVB2] : -# 793| v0_14(void) = Call : func:r0_13, this:r0_12 -# 793| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_16(glval) = FieldAddress[derivedvb_s] : r0_3 -# 793| r0_17(glval) = FunctionAddress[String] : -# 793| v0_18(void) = Call : func:r0_17, this:r0_16 -# 793| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 794| v0_20(void) = NoOp : -# 793| v0_21(void) = ReturnVoid : -# 793| v0_22(void) = UnmodeledUse : mu* -# 793| v0_23(void) = AliasedUse : ~mu0_2 -# 793| v0_24(void) = ExitFunction : +# 793| v0_0(void) = EnterFunction : +# 793| mu0_1(unknown) = AliasedDefinition : +# 793| mu0_2(unknown) = UnmodeledDefinition : +# 793| r0_3(glval) = InitializeThis : +# 793| r0_4(glval) = ConvertToNonVirtualBase[DerivedVB : Base] : r0_3 +# 793| r0_5(glval) = FunctionAddress[Base] : +# 793| v0_6(void) = Call : func:r0_5, this:r0_4 +# 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_8(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB1] : r0_3 +# 793| r0_9(glval) = FunctionAddress[MiddleVB1] : +# 793| v0_10(void) = Call : func:r0_9, this:r0_8 +# 793| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_12(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB2] : r0_3 +# 793| r0_13(glval) = FunctionAddress[MiddleVB2] : +# 793| v0_14(void) = Call : func:r0_13, this:r0_12 +# 793| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 793| r0_16(glval) = FieldAddress[derivedvb_s] : r0_3 +# 793| r0_17(glval) = FunctionAddress[String] : +# 793| v0_18(void) = Call : func:r0_17, this:r0_16 +# 793| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 794| v0_20(void) = NoOp : +# 793| v0_21(void) = ReturnVoid : +# 793| v0_22(void) = UnmodeledUse : mu* +# 793| v0_23(void) = AliasedUse : ~mu0_2 +# 793| v0_24(void) = ExitFunction : # 795| void DerivedVB::~DerivedVB() # 795| Block 0 -# 795| v0_0(void) = EnterFunction : -# 795| mu0_1(unknown) = AliasedDefinition : -# 795| mu0_2(unknown) = UnmodeledDefinition : -# 795| r0_3(glval) = InitializeThis : -# 796| v0_4(void) = NoOp : -# 796| r0_5(glval) = FieldAddress[derivedvb_s] : r0_3 -# 796| r0_6(glval) = FunctionAddress[~String] : -# 796| v0_7(void) = Call : func:r0_6, this:r0_5 -# 796| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_9(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 -# 796| r0_10(glval) = FunctionAddress[~MiddleVB2] : -# 796| v0_11(void) = Call : func:r0_10, this:r0_9 -# 796| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_13(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 -# 796| r0_14(glval) = FunctionAddress[~MiddleVB1] : -# 796| v0_15(void) = Call : func:r0_14, this:r0_13 -# 796| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 -# 796| r0_17(glval) = ConvertToBase[DerivedVB : Base] : r0_3 -# 796| r0_18(glval) = FunctionAddress[~Base] : -# 796| v0_19(void) = Call : func:r0_18, this:r0_17 -# 796| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 795| v0_21(void) = ReturnVoid : -# 795| v0_22(void) = UnmodeledUse : mu* -# 795| v0_23(void) = AliasedUse : ~mu0_2 -# 795| v0_24(void) = ExitFunction : +# 795| v0_0(void) = EnterFunction : +# 795| mu0_1(unknown) = AliasedDefinition : +# 795| mu0_2(unknown) = UnmodeledDefinition : +# 795| r0_3(glval) = InitializeThis : +# 796| v0_4(void) = NoOp : +# 796| r0_5(glval) = FieldAddress[derivedvb_s] : r0_3 +# 796| r0_6(glval) = FunctionAddress[~String] : +# 796| v0_7(void) = Call : func:r0_6, this:r0_5 +# 796| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_9(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB2] : r0_3 +# 796| r0_10(glval) = FunctionAddress[~MiddleVB2] : +# 796| v0_11(void) = Call : func:r0_10, this:r0_9 +# 796| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_13(glval) = ConvertToNonVirtualBase[DerivedVB : MiddleVB1] : r0_3 +# 796| r0_14(glval) = FunctionAddress[~MiddleVB1] : +# 796| v0_15(void) = Call : func:r0_14, this:r0_13 +# 796| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +# 796| r0_17(glval) = ConvertToNonVirtualBase[DerivedVB : Base] : r0_3 +# 796| r0_18(glval) = FunctionAddress[~Base] : +# 796| v0_19(void) = Call : func:r0_18, this:r0_17 +# 796| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 795| v0_21(void) = ReturnVoid : +# 795| v0_22(void) = UnmodeledUse : mu* +# 795| v0_23(void) = AliasedUse : ~mu0_2 +# 795| v0_24(void) = ExitFunction : # 799| void HierarchyConversions() # 799| Block 0 -# 799| v0_0(void) = EnterFunction : -# 799| mu0_1(unknown) = AliasedDefinition : -# 799| mu0_2(unknown) = UnmodeledDefinition : -# 800| r0_3(glval) = VariableAddress[b] : -# 800| r0_4(glval) = FunctionAddress[Base] : -# 800| v0_5(void) = Call : func:r0_4, this:r0_3 -# 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 801| r0_7(glval) = VariableAddress[m] : -# 801| r0_8(glval) = FunctionAddress[Middle] : -# 801| v0_9(void) = Call : func:r0_8, this:r0_7 -# 801| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 802| r0_11(glval) = VariableAddress[d] : -# 802| r0_12(glval) = FunctionAddress[Derived] : -# 802| v0_13(void) = Call : func:r0_12, this:r0_11 -# 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 804| r0_15(glval) = VariableAddress[pb] : -# 804| r0_16(glval) = VariableAddress[b] : -# 804| mu0_17(Base *) = Store : &:r0_15, r0_16 -# 805| r0_18(glval) = VariableAddress[pm] : -# 805| r0_19(glval) = VariableAddress[m] : -# 805| mu0_20(Middle *) = Store : &:r0_18, r0_19 -# 806| r0_21(glval) = VariableAddress[pd] : -# 806| r0_22(glval) = VariableAddress[d] : -# 806| mu0_23(Derived *) = Store : &:r0_21, r0_22 -# 808| r0_24(glval) = VariableAddress[b] : -# 808| r0_25(glval) = FunctionAddress[operator=] : -# 808| r0_26(glval) = VariableAddress[m] : -# 808| r0_27(glval) = ConvertToBase[Middle : Base] : r0_26 -# 808| r0_28(Base &) = Call : func:r0_25, this:r0_24, 0:r0_27 -# 808| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 808| v0_30(void) = ^BufferReadSideEffect[-1] : &:r0_24, ~mu0_2 -# 808| v0_31(void) = ^BufferReadSideEffect[0] : &:r0_27, ~mu0_2 -# 808| mu0_32(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 -# 808| mu0_33(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_27 -# 809| r0_34(glval) = VariableAddress[b] : -# 809| r0_35(glval) = FunctionAddress[operator=] : -# 809| r0_36(glval) = FunctionAddress[Base] : -# 809| r0_37(glval) = VariableAddress[m] : -# 809| r0_38(glval) = ConvertToBase[Middle : Base] : r0_37 -# 809| v0_39(void) = Call : func:r0_36, 0:r0_38 -# 809| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_41(void) = ^BufferReadSideEffect[0] : &:r0_38, ~mu0_2 -# 809| mu0_42(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 -# 809| r0_43(glval) = Convert : v0_39 -# 809| r0_44(Base &) = Call : func:r0_35, this:r0_34, 0:r0_43 -# 809| mu0_45(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_46(void) = ^BufferReadSideEffect[-1] : &:r0_34, ~mu0_2 -# 809| v0_47(void) = ^BufferReadSideEffect[0] : &:r0_43, ~mu0_2 -# 809| mu0_48(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_34 -# 809| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_43 -# 810| r0_50(glval) = VariableAddress[b] : -# 810| r0_51(glval) = FunctionAddress[operator=] : -# 810| r0_52(glval) = FunctionAddress[Base] : -# 810| r0_53(glval) = VariableAddress[m] : -# 810| r0_54(glval) = ConvertToBase[Middle : Base] : r0_53 -# 810| v0_55(void) = Call : func:r0_52, 0:r0_54 -# 810| mu0_56(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_57(void) = ^BufferReadSideEffect[0] : &:r0_54, ~mu0_2 -# 810| mu0_58(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_54 -# 810| r0_59(glval) = Convert : v0_55 -# 810| r0_60(Base &) = Call : func:r0_51, this:r0_50, 0:r0_59 -# 810| mu0_61(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_62(void) = ^BufferReadSideEffect[-1] : &:r0_50, ~mu0_2 -# 810| v0_63(void) = ^BufferReadSideEffect[0] : &:r0_59, ~mu0_2 -# 810| mu0_64(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_50 -# 810| mu0_65(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_59 -# 811| r0_66(glval) = VariableAddress[pm] : -# 811| r0_67(Middle *) = Load : &:r0_66, ~mu0_2 -# 811| r0_68(Base *) = ConvertToBase[Middle : Base] : r0_67 -# 811| r0_69(glval) = VariableAddress[pb] : -# 811| mu0_70(Base *) = Store : &:r0_69, r0_68 -# 812| r0_71(glval) = VariableAddress[pm] : -# 812| r0_72(Middle *) = Load : &:r0_71, ~mu0_2 -# 812| r0_73(Base *) = ConvertToBase[Middle : Base] : r0_72 -# 812| r0_74(glval) = VariableAddress[pb] : -# 812| mu0_75(Base *) = Store : &:r0_74, r0_73 -# 813| r0_76(glval) = VariableAddress[pm] : -# 813| r0_77(Middle *) = Load : &:r0_76, ~mu0_2 -# 813| r0_78(Base *) = ConvertToBase[Middle : Base] : r0_77 -# 813| r0_79(glval) = VariableAddress[pb] : -# 813| mu0_80(Base *) = Store : &:r0_79, r0_78 -# 814| r0_81(glval) = VariableAddress[pm] : -# 814| r0_82(Middle *) = Load : &:r0_81, ~mu0_2 -# 814| r0_83(Base *) = Convert : r0_82 -# 814| r0_84(glval) = VariableAddress[pb] : -# 814| mu0_85(Base *) = Store : &:r0_84, r0_83 -# 816| r0_86(glval) = VariableAddress[m] : -# 816| r0_87(glval) = FunctionAddress[operator=] : -# 816| r0_88(glval) = VariableAddress[b] : -# 816| r0_89(glval) = ConvertToDerived[Middle : Base] : r0_88 -# 816| r0_90(glval) = Convert : r0_89 -# 816| r0_91(Middle &) = Call : func:r0_87, this:r0_86, 0:r0_90 -# 816| mu0_92(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_93(void) = ^BufferReadSideEffect[-1] : &:r0_86, ~mu0_2 -# 816| v0_94(void) = ^BufferReadSideEffect[0] : &:r0_90, ~mu0_2 -# 816| mu0_95(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_86 -# 816| mu0_96(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_90 -# 817| r0_97(glval) = VariableAddress[m] : -# 817| r0_98(glval) = FunctionAddress[operator=] : -# 817| r0_99(glval) = VariableAddress[b] : -# 817| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 -# 817| r0_101(glval) = Convert : r0_100 -# 817| r0_102(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_101 -# 817| mu0_103(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_104(void) = ^BufferReadSideEffect[-1] : &:r0_97, ~mu0_2 -# 817| v0_105(void) = ^BufferReadSideEffect[0] : &:r0_101, ~mu0_2 -# 817| mu0_106(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 -# 817| mu0_107(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_101 -# 818| r0_108(glval) = VariableAddress[pb] : -# 818| r0_109(Base *) = Load : &:r0_108, ~mu0_2 -# 818| r0_110(Middle *) = ConvertToDerived[Middle : Base] : r0_109 -# 818| r0_111(glval) = VariableAddress[pm] : -# 818| mu0_112(Middle *) = Store : &:r0_111, r0_110 -# 819| r0_113(glval) = VariableAddress[pb] : -# 819| r0_114(Base *) = Load : &:r0_113, ~mu0_2 -# 819| r0_115(Middle *) = ConvertToDerived[Middle : Base] : r0_114 -# 819| r0_116(glval) = VariableAddress[pm] : -# 819| mu0_117(Middle *) = Store : &:r0_116, r0_115 -# 820| r0_118(glval) = VariableAddress[pb] : -# 820| r0_119(Base *) = Load : &:r0_118, ~mu0_2 -# 820| r0_120(Middle *) = Convert : r0_119 -# 820| r0_121(glval) = VariableAddress[pm] : -# 820| mu0_122(Middle *) = Store : &:r0_121, r0_120 -# 822| r0_123(glval) = VariableAddress[b] : -# 822| r0_124(glval) = FunctionAddress[operator=] : -# 822| r0_125(glval) = VariableAddress[d] : -# 822| r0_126(glval) = ConvertToBase[Derived : Middle] : r0_125 -# 822| r0_127(glval) = ConvertToBase[Middle : Base] : r0_126 -# 822| r0_128(Base &) = Call : func:r0_124, this:r0_123, 0:r0_127 -# 822| mu0_129(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_130(void) = ^BufferReadSideEffect[-1] : &:r0_123, ~mu0_2 -# 822| v0_131(void) = ^BufferReadSideEffect[0] : &:r0_127, ~mu0_2 -# 822| mu0_132(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_123 -# 822| mu0_133(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_127 -# 823| r0_134(glval) = VariableAddress[b] : -# 823| r0_135(glval) = FunctionAddress[operator=] : -# 823| r0_136(glval) = FunctionAddress[Base] : -# 823| r0_137(glval) = VariableAddress[d] : -# 823| r0_138(glval) = ConvertToBase[Derived : Middle] : r0_137 -# 823| r0_139(glval) = ConvertToBase[Middle : Base] : r0_138 -# 823| v0_140(void) = Call : func:r0_136, 0:r0_139 -# 823| mu0_141(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_142(void) = ^BufferReadSideEffect[0] : &:r0_139, ~mu0_2 -# 823| mu0_143(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_139 -# 823| r0_144(glval) = Convert : v0_140 -# 823| r0_145(Base &) = Call : func:r0_135, this:r0_134, 0:r0_144 -# 823| mu0_146(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_147(void) = ^BufferReadSideEffect[-1] : &:r0_134, ~mu0_2 -# 823| v0_148(void) = ^BufferReadSideEffect[0] : &:r0_144, ~mu0_2 -# 823| mu0_149(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_134 -# 823| mu0_150(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 -# 824| r0_151(glval) = VariableAddress[b] : -# 824| r0_152(glval) = FunctionAddress[operator=] : -# 824| r0_153(glval) = FunctionAddress[Base] : -# 824| r0_154(glval) = VariableAddress[d] : -# 824| r0_155(glval) = ConvertToBase[Derived : Middle] : r0_154 -# 824| r0_156(glval) = ConvertToBase[Middle : Base] : r0_155 -# 824| v0_157(void) = Call : func:r0_153, 0:r0_156 -# 824| mu0_158(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_159(void) = ^BufferReadSideEffect[0] : &:r0_156, ~mu0_2 -# 824| mu0_160(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_156 -# 824| r0_161(glval) = Convert : v0_157 -# 824| r0_162(Base &) = Call : func:r0_152, this:r0_151, 0:r0_161 -# 824| mu0_163(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_164(void) = ^BufferReadSideEffect[-1] : &:r0_151, ~mu0_2 -# 824| v0_165(void) = ^BufferReadSideEffect[0] : &:r0_161, ~mu0_2 -# 824| mu0_166(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 -# 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_161 -# 825| r0_168(glval) = VariableAddress[pd] : -# 825| r0_169(Derived *) = Load : &:r0_168, ~mu0_2 -# 825| r0_170(Middle *) = ConvertToBase[Derived : Middle] : r0_169 -# 825| r0_171(Base *) = ConvertToBase[Middle : Base] : r0_170 -# 825| r0_172(glval) = VariableAddress[pb] : -# 825| mu0_173(Base *) = Store : &:r0_172, r0_171 -# 826| r0_174(glval) = VariableAddress[pd] : -# 826| r0_175(Derived *) = Load : &:r0_174, ~mu0_2 -# 826| r0_176(Middle *) = ConvertToBase[Derived : Middle] : r0_175 -# 826| r0_177(Base *) = ConvertToBase[Middle : Base] : r0_176 -# 826| r0_178(glval) = VariableAddress[pb] : -# 826| mu0_179(Base *) = Store : &:r0_178, r0_177 -# 827| r0_180(glval) = VariableAddress[pd] : -# 827| r0_181(Derived *) = Load : &:r0_180, ~mu0_2 -# 827| r0_182(Middle *) = ConvertToBase[Derived : Middle] : r0_181 -# 827| r0_183(Base *) = ConvertToBase[Middle : Base] : r0_182 -# 827| r0_184(glval) = VariableAddress[pb] : -# 827| mu0_185(Base *) = Store : &:r0_184, r0_183 -# 828| r0_186(glval) = VariableAddress[pd] : -# 828| r0_187(Derived *) = Load : &:r0_186, ~mu0_2 -# 828| r0_188(Base *) = Convert : r0_187 -# 828| r0_189(glval) = VariableAddress[pb] : -# 828| mu0_190(Base *) = Store : &:r0_189, r0_188 -# 830| r0_191(glval) = VariableAddress[d] : -# 830| r0_192(glval) = FunctionAddress[operator=] : -# 830| r0_193(glval) = VariableAddress[b] : -# 830| r0_194(glval) = ConvertToDerived[Middle : Base] : r0_193 -# 830| r0_195(glval) = ConvertToDerived[Derived : Middle] : r0_194 -# 830| r0_196(glval) = Convert : r0_195 -# 830| r0_197(Derived &) = Call : func:r0_192, this:r0_191, 0:r0_196 -# 830| mu0_198(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_199(void) = ^BufferReadSideEffect[-1] : &:r0_191, ~mu0_2 -# 830| v0_200(void) = ^BufferReadSideEffect[0] : &:r0_196, ~mu0_2 -# 830| mu0_201(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_191 -# 830| mu0_202(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_196 -# 831| r0_203(glval) = VariableAddress[d] : -# 831| r0_204(glval) = FunctionAddress[operator=] : -# 831| r0_205(glval) = VariableAddress[b] : -# 831| r0_206(glval) = ConvertToDerived[Middle : Base] : r0_205 -# 831| r0_207(glval) = ConvertToDerived[Derived : Middle] : r0_206 -# 831| r0_208(glval) = Convert : r0_207 -# 831| r0_209(Derived &) = Call : func:r0_204, this:r0_203, 0:r0_208 -# 831| mu0_210(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_211(void) = ^BufferReadSideEffect[-1] : &:r0_203, ~mu0_2 -# 831| v0_212(void) = ^BufferReadSideEffect[0] : &:r0_208, ~mu0_2 -# 831| mu0_213(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_203 -# 831| mu0_214(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_208 -# 832| r0_215(glval) = VariableAddress[pb] : -# 832| r0_216(Base *) = Load : &:r0_215, ~mu0_2 -# 832| r0_217(Middle *) = ConvertToDerived[Middle : Base] : r0_216 -# 832| r0_218(Derived *) = ConvertToDerived[Derived : Middle] : r0_217 -# 832| r0_219(glval) = VariableAddress[pd] : -# 832| mu0_220(Derived *) = Store : &:r0_219, r0_218 -# 833| r0_221(glval) = VariableAddress[pb] : -# 833| r0_222(Base *) = Load : &:r0_221, ~mu0_2 -# 833| r0_223(Middle *) = ConvertToDerived[Middle : Base] : r0_222 -# 833| r0_224(Derived *) = ConvertToDerived[Derived : Middle] : r0_223 -# 833| r0_225(glval) = VariableAddress[pd] : -# 833| mu0_226(Derived *) = Store : &:r0_225, r0_224 -# 834| r0_227(glval) = VariableAddress[pb] : -# 834| r0_228(Base *) = Load : &:r0_227, ~mu0_2 -# 834| r0_229(Derived *) = Convert : r0_228 -# 834| r0_230(glval) = VariableAddress[pd] : -# 834| mu0_231(Derived *) = Store : &:r0_230, r0_229 -# 836| r0_232(glval) = VariableAddress[pmv] : -# 836| r0_233(MiddleVB1 *) = Constant[0] : -# 836| mu0_234(MiddleVB1 *) = Store : &:r0_232, r0_233 -# 837| r0_235(glval) = VariableAddress[pdv] : -# 837| r0_236(DerivedVB *) = Constant[0] : -# 837| mu0_237(DerivedVB *) = Store : &:r0_235, r0_236 -# 838| r0_238(glval) = VariableAddress[pmv] : -# 838| r0_239(MiddleVB1 *) = Load : &:r0_238, ~mu0_2 -# 838| r0_240(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_239 -# 838| r0_241(glval) = VariableAddress[pb] : -# 838| mu0_242(Base *) = Store : &:r0_241, r0_240 -# 839| r0_243(glval) = VariableAddress[pdv] : -# 839| r0_244(DerivedVB *) = Load : &:r0_243, ~mu0_2 -# 839| r0_245(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_244 -# 839| r0_246(glval) = VariableAddress[pb] : -# 839| mu0_247(Base *) = Store : &:r0_246, r0_245 -# 840| v0_248(void) = NoOp : -# 799| v0_249(void) = ReturnVoid : -# 799| v0_250(void) = UnmodeledUse : mu* -# 799| v0_251(void) = AliasedUse : ~mu0_2 -# 799| v0_252(void) = ExitFunction : +# 799| v0_0(void) = EnterFunction : +# 799| mu0_1(unknown) = AliasedDefinition : +# 799| mu0_2(unknown) = UnmodeledDefinition : +# 800| r0_3(glval) = VariableAddress[b] : +# 800| r0_4(glval) = FunctionAddress[Base] : +# 800| v0_5(void) = Call : func:r0_4, this:r0_3 +# 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 +# 801| r0_7(glval) = VariableAddress[m] : +# 801| r0_8(glval) = FunctionAddress[Middle] : +# 801| v0_9(void) = Call : func:r0_8, this:r0_7 +# 801| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 +# 802| r0_11(glval) = VariableAddress[d] : +# 802| r0_12(glval) = FunctionAddress[Derived] : +# 802| v0_13(void) = Call : func:r0_12, this:r0_11 +# 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +# 804| r0_15(glval) = VariableAddress[pb] : +# 804| r0_16(glval) = VariableAddress[b] : +# 804| r0_17(Base *) = CopyValue : r0_16 +# 804| mu0_18(Base *) = Store : &:r0_15, r0_17 +# 805| r0_19(glval) = VariableAddress[pm] : +# 805| r0_20(glval) = VariableAddress[m] : +# 805| r0_21(Middle *) = CopyValue : r0_20 +# 805| mu0_22(Middle *) = Store : &:r0_19, r0_21 +# 806| r0_23(glval) = VariableAddress[pd] : +# 806| r0_24(glval) = VariableAddress[d] : +# 806| r0_25(Derived *) = CopyValue : r0_24 +# 806| mu0_26(Derived *) = Store : &:r0_23, r0_25 +# 808| r0_27(glval) = VariableAddress[b] : +# 808| r0_28(glval) = FunctionAddress[operator=] : +# 808| r0_29(glval) = VariableAddress[m] : +# 808| r0_30(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_29 +# 808| r0_31(Base &) = CopyValue : r0_30 +# 808| r0_32(Base &) = Call : func:r0_28, this:r0_27, 0:r0_31 +# 808| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 808| v0_34(void) = ^BufferReadSideEffect[-1] : &:r0_27, ~mu0_2 +# 808| v0_35(void) = ^BufferReadSideEffect[0] : &:r0_31, ~mu0_2 +# 808| mu0_36(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 +# 808| mu0_37(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_31 +# 808| r0_38(glval) = CopyValue : r0_32 +# 809| r0_39(glval) = VariableAddress[b] : +# 809| r0_40(glval) = FunctionAddress[operator=] : +# 809| r0_41(glval) = FunctionAddress[Base] : +# 809| r0_42(glval) = VariableAddress[m] : +# 809| r0_43(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_42 +# 809| r0_44(Base &) = CopyValue : r0_43 +# 809| v0_45(void) = Call : func:r0_41, 0:r0_44 +# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_47(void) = ^BufferReadSideEffect[0] : &:r0_44, ~mu0_2 +# 809| mu0_48(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_44 +# 809| r0_49(glval) = Convert : v0_45 +# 809| r0_50(Base &) = CopyValue : r0_49 +# 809| r0_51(Base &) = Call : func:r0_40, this:r0_39, 0:r0_50 +# 809| mu0_52(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_53(void) = ^BufferReadSideEffect[-1] : &:r0_39, ~mu0_2 +# 809| v0_54(void) = ^BufferReadSideEffect[0] : &:r0_50, ~mu0_2 +# 809| mu0_55(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_39 +# 809| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_50 +# 809| r0_57(glval) = CopyValue : r0_51 +# 810| r0_58(glval) = VariableAddress[b] : +# 810| r0_59(glval) = FunctionAddress[operator=] : +# 810| r0_60(glval) = FunctionAddress[Base] : +# 810| r0_61(glval) = VariableAddress[m] : +# 810| r0_62(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_61 +# 810| r0_63(Base &) = CopyValue : r0_62 +# 810| v0_64(void) = Call : func:r0_60, 0:r0_63 +# 810| mu0_65(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_66(void) = ^BufferReadSideEffect[0] : &:r0_63, ~mu0_2 +# 810| mu0_67(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_63 +# 810| r0_68(glval) = Convert : v0_64 +# 810| r0_69(Base &) = CopyValue : r0_68 +# 810| r0_70(Base &) = Call : func:r0_59, this:r0_58, 0:r0_69 +# 810| mu0_71(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_72(void) = ^BufferReadSideEffect[-1] : &:r0_58, ~mu0_2 +# 810| v0_73(void) = ^BufferReadSideEffect[0] : &:r0_69, ~mu0_2 +# 810| mu0_74(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_58 +# 810| mu0_75(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_69 +# 810| r0_76(glval) = CopyValue : r0_70 +# 811| r0_77(glval) = VariableAddress[pm] : +# 811| r0_78(Middle *) = Load : &:r0_77, ~mu0_2 +# 811| r0_79(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_78 +# 811| r0_80(glval) = VariableAddress[pb] : +# 811| mu0_81(Base *) = Store : &:r0_80, r0_79 +# 812| r0_82(glval) = VariableAddress[pm] : +# 812| r0_83(Middle *) = Load : &:r0_82, ~mu0_2 +# 812| r0_84(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_83 +# 812| r0_85(glval) = VariableAddress[pb] : +# 812| mu0_86(Base *) = Store : &:r0_85, r0_84 +# 813| r0_87(glval) = VariableAddress[pm] : +# 813| r0_88(Middle *) = Load : &:r0_87, ~mu0_2 +# 813| r0_89(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_88 +# 813| r0_90(glval) = VariableAddress[pb] : +# 813| mu0_91(Base *) = Store : &:r0_90, r0_89 +# 814| r0_92(glval) = VariableAddress[pm] : +# 814| r0_93(Middle *) = Load : &:r0_92, ~mu0_2 +# 814| r0_94(Base *) = Convert : r0_93 +# 814| r0_95(glval) = VariableAddress[pb] : +# 814| mu0_96(Base *) = Store : &:r0_95, r0_94 +# 816| r0_97(glval) = VariableAddress[m] : +# 816| r0_98(glval) = FunctionAddress[operator=] : +# 816| r0_99(glval) = VariableAddress[b] : +# 816| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 +# 816| r0_101(glval) = Convert : r0_100 +# 816| r0_102(Middle &) = CopyValue : r0_101 +# 816| r0_103(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_102 +# 816| mu0_104(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_105(void) = ^BufferReadSideEffect[-1] : &:r0_97, ~mu0_2 +# 816| v0_106(void) = ^BufferReadSideEffect[0] : &:r0_102, ~mu0_2 +# 816| mu0_107(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 +# 816| mu0_108(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_102 +# 816| r0_109(glval) = CopyValue : r0_103 +# 817| r0_110(glval) = VariableAddress[m] : +# 817| r0_111(glval) = FunctionAddress[operator=] : +# 817| r0_112(glval) = VariableAddress[b] : +# 817| r0_113(glval) = ConvertToDerived[Middle : Base] : r0_112 +# 817| r0_114(glval) = Convert : r0_113 +# 817| r0_115(Middle &) = CopyValue : r0_114 +# 817| r0_116(Middle &) = Call : func:r0_111, this:r0_110, 0:r0_115 +# 817| mu0_117(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_118(void) = ^BufferReadSideEffect[-1] : &:r0_110, ~mu0_2 +# 817| v0_119(void) = ^BufferReadSideEffect[0] : &:r0_115, ~mu0_2 +# 817| mu0_120(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 +# 817| mu0_121(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_115 +# 817| r0_122(glval) = CopyValue : r0_116 +# 818| r0_123(glval) = VariableAddress[pb] : +# 818| r0_124(Base *) = Load : &:r0_123, ~mu0_2 +# 818| r0_125(Middle *) = ConvertToDerived[Middle : Base] : r0_124 +# 818| r0_126(glval) = VariableAddress[pm] : +# 818| mu0_127(Middle *) = Store : &:r0_126, r0_125 +# 819| r0_128(glval) = VariableAddress[pb] : +# 819| r0_129(Base *) = Load : &:r0_128, ~mu0_2 +# 819| r0_130(Middle *) = ConvertToDerived[Middle : Base] : r0_129 +# 819| r0_131(glval) = VariableAddress[pm] : +# 819| mu0_132(Middle *) = Store : &:r0_131, r0_130 +# 820| r0_133(glval) = VariableAddress[pb] : +# 820| r0_134(Base *) = Load : &:r0_133, ~mu0_2 +# 820| r0_135(Middle *) = Convert : r0_134 +# 820| r0_136(glval) = VariableAddress[pm] : +# 820| mu0_137(Middle *) = Store : &:r0_136, r0_135 +# 822| r0_138(glval) = VariableAddress[b] : +# 822| r0_139(glval) = FunctionAddress[operator=] : +# 822| r0_140(glval) = VariableAddress[d] : +# 822| r0_141(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_140 +# 822| r0_142(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_141 +# 822| r0_143(Base &) = CopyValue : r0_142 +# 822| r0_144(Base &) = Call : func:r0_139, this:r0_138, 0:r0_143 +# 822| mu0_145(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_146(void) = ^BufferReadSideEffect[-1] : &:r0_138, ~mu0_2 +# 822| v0_147(void) = ^BufferReadSideEffect[0] : &:r0_143, ~mu0_2 +# 822| mu0_148(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_138 +# 822| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_143 +# 822| r0_150(glval) = CopyValue : r0_144 +# 823| r0_151(glval) = VariableAddress[b] : +# 823| r0_152(glval) = FunctionAddress[operator=] : +# 823| r0_153(glval) = FunctionAddress[Base] : +# 823| r0_154(glval) = VariableAddress[d] : +# 823| r0_155(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_154 +# 823| r0_156(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_155 +# 823| r0_157(Base &) = CopyValue : r0_156 +# 823| v0_158(void) = Call : func:r0_153, 0:r0_157 +# 823| mu0_159(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_160(void) = ^BufferReadSideEffect[0] : &:r0_157, ~mu0_2 +# 823| mu0_161(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_157 +# 823| r0_162(glval) = Convert : v0_158 +# 823| r0_163(Base &) = CopyValue : r0_162 +# 823| r0_164(Base &) = Call : func:r0_152, this:r0_151, 0:r0_163 +# 823| mu0_165(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_166(void) = ^BufferReadSideEffect[-1] : &:r0_151, ~mu0_2 +# 823| v0_167(void) = ^BufferReadSideEffect[0] : &:r0_163, ~mu0_2 +# 823| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 +# 823| mu0_169(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_163 +# 823| r0_170(glval) = CopyValue : r0_164 +# 824| r0_171(glval) = VariableAddress[b] : +# 824| r0_172(glval) = FunctionAddress[operator=] : +# 824| r0_173(glval) = FunctionAddress[Base] : +# 824| r0_174(glval) = VariableAddress[d] : +# 824| r0_175(glval) = ConvertToNonVirtualBase[Derived : Middle] : r0_174 +# 824| r0_176(glval) = ConvertToNonVirtualBase[Middle : Base] : r0_175 +# 824| r0_177(Base &) = CopyValue : r0_176 +# 824| v0_178(void) = Call : func:r0_173, 0:r0_177 +# 824| mu0_179(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_180(void) = ^BufferReadSideEffect[0] : &:r0_177, ~mu0_2 +# 824| mu0_181(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_177 +# 824| r0_182(glval) = Convert : v0_178 +# 824| r0_183(Base &) = CopyValue : r0_182 +# 824| r0_184(Base &) = Call : func:r0_172, this:r0_171, 0:r0_183 +# 824| mu0_185(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_186(void) = ^BufferReadSideEffect[-1] : &:r0_171, ~mu0_2 +# 824| v0_187(void) = ^BufferReadSideEffect[0] : &:r0_183, ~mu0_2 +# 824| mu0_188(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_171 +# 824| mu0_189(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_183 +# 824| r0_190(glval) = CopyValue : r0_184 +# 825| r0_191(glval) = VariableAddress[pd] : +# 825| r0_192(Derived *) = Load : &:r0_191, ~mu0_2 +# 825| r0_193(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_192 +# 825| r0_194(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_193 +# 825| r0_195(glval) = VariableAddress[pb] : +# 825| mu0_196(Base *) = Store : &:r0_195, r0_194 +# 826| r0_197(glval) = VariableAddress[pd] : +# 826| r0_198(Derived *) = Load : &:r0_197, ~mu0_2 +# 826| r0_199(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_198 +# 826| r0_200(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_199 +# 826| r0_201(glval) = VariableAddress[pb] : +# 826| mu0_202(Base *) = Store : &:r0_201, r0_200 +# 827| r0_203(glval) = VariableAddress[pd] : +# 827| r0_204(Derived *) = Load : &:r0_203, ~mu0_2 +# 827| r0_205(Middle *) = ConvertToNonVirtualBase[Derived : Middle] : r0_204 +# 827| r0_206(Base *) = ConvertToNonVirtualBase[Middle : Base] : r0_205 +# 827| r0_207(glval) = VariableAddress[pb] : +# 827| mu0_208(Base *) = Store : &:r0_207, r0_206 +# 828| r0_209(glval) = VariableAddress[pd] : +# 828| r0_210(Derived *) = Load : &:r0_209, ~mu0_2 +# 828| r0_211(Base *) = Convert : r0_210 +# 828| r0_212(glval) = VariableAddress[pb] : +# 828| mu0_213(Base *) = Store : &:r0_212, r0_211 +# 830| r0_214(glval) = VariableAddress[d] : +# 830| r0_215(glval) = FunctionAddress[operator=] : +# 830| r0_216(glval) = VariableAddress[b] : +# 830| r0_217(glval) = ConvertToDerived[Middle : Base] : r0_216 +# 830| r0_218(glval) = ConvertToDerived[Derived : Middle] : r0_217 +# 830| r0_219(glval) = Convert : r0_218 +# 830| r0_220(Derived &) = CopyValue : r0_219 +# 830| r0_221(Derived &) = Call : func:r0_215, this:r0_214, 0:r0_220 +# 830| mu0_222(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_223(void) = ^BufferReadSideEffect[-1] : &:r0_214, ~mu0_2 +# 830| v0_224(void) = ^BufferReadSideEffect[0] : &:r0_220, ~mu0_2 +# 830| mu0_225(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_214 +# 830| mu0_226(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_220 +# 830| r0_227(glval) = CopyValue : r0_221 +# 831| r0_228(glval) = VariableAddress[d] : +# 831| r0_229(glval) = FunctionAddress[operator=] : +# 831| r0_230(glval) = VariableAddress[b] : +# 831| r0_231(glval) = ConvertToDerived[Middle : Base] : r0_230 +# 831| r0_232(glval) = ConvertToDerived[Derived : Middle] : r0_231 +# 831| r0_233(glval) = Convert : r0_232 +# 831| r0_234(Derived &) = CopyValue : r0_233 +# 831| r0_235(Derived &) = Call : func:r0_229, this:r0_228, 0:r0_234 +# 831| mu0_236(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_237(void) = ^BufferReadSideEffect[-1] : &:r0_228, ~mu0_2 +# 831| v0_238(void) = ^BufferReadSideEffect[0] : &:r0_234, ~mu0_2 +# 831| mu0_239(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_228 +# 831| mu0_240(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_234 +# 831| r0_241(glval) = CopyValue : r0_235 +# 832| r0_242(glval) = VariableAddress[pb] : +# 832| r0_243(Base *) = Load : &:r0_242, ~mu0_2 +# 832| r0_244(Middle *) = ConvertToDerived[Middle : Base] : r0_243 +# 832| r0_245(Derived *) = ConvertToDerived[Derived : Middle] : r0_244 +# 832| r0_246(glval) = VariableAddress[pd] : +# 832| mu0_247(Derived *) = Store : &:r0_246, r0_245 +# 833| r0_248(glval) = VariableAddress[pb] : +# 833| r0_249(Base *) = Load : &:r0_248, ~mu0_2 +# 833| r0_250(Middle *) = ConvertToDerived[Middle : Base] : r0_249 +# 833| r0_251(Derived *) = ConvertToDerived[Derived : Middle] : r0_250 +# 833| r0_252(glval) = VariableAddress[pd] : +# 833| mu0_253(Derived *) = Store : &:r0_252, r0_251 +# 834| r0_254(glval) = VariableAddress[pb] : +# 834| r0_255(Base *) = Load : &:r0_254, ~mu0_2 +# 834| r0_256(Derived *) = Convert : r0_255 +# 834| r0_257(glval) = VariableAddress[pd] : +# 834| mu0_258(Derived *) = Store : &:r0_257, r0_256 +# 836| r0_259(glval) = VariableAddress[pmv] : +# 836| r0_260(MiddleVB1 *) = Constant[0] : +# 836| mu0_261(MiddleVB1 *) = Store : &:r0_259, r0_260 +# 837| r0_262(glval) = VariableAddress[pdv] : +# 837| r0_263(DerivedVB *) = Constant[0] : +# 837| mu0_264(DerivedVB *) = Store : &:r0_262, r0_263 +# 838| r0_265(glval) = VariableAddress[pmv] : +# 838| r0_266(MiddleVB1 *) = Load : &:r0_265, ~mu0_2 +# 838| r0_267(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_266 +# 838| r0_268(glval) = VariableAddress[pb] : +# 838| mu0_269(Base *) = Store : &:r0_268, r0_267 +# 839| r0_270(glval) = VariableAddress[pdv] : +# 839| r0_271(DerivedVB *) = Load : &:r0_270, ~mu0_2 +# 839| r0_272(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_271 +# 839| r0_273(glval) = VariableAddress[pb] : +# 839| mu0_274(Base *) = Store : &:r0_273, r0_272 +# 840| v0_275(void) = NoOp : +# 799| v0_276(void) = ReturnVoid : +# 799| v0_277(void) = UnmodeledUse : mu* +# 799| v0_278(void) = AliasedUse : ~mu0_2 +# 799| v0_279(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -3982,35 +4093,35 @@ ir.cpp: # 846| void PolymorphicDerived::PolymorphicDerived() # 846| Block 0 -# 846| v0_0(void) = EnterFunction : -# 846| mu0_1(unknown) = AliasedDefinition : -# 846| mu0_2(unknown) = UnmodeledDefinition : -# 846| r0_3(glval) = InitializeThis : -# 846| r0_4(glval) = ConvertToBase[PolymorphicDerived : PolymorphicBase] : r0_3 -# 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : -# 846| v0_6(void) = Call : func:r0_5, this:r0_4 -# 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 846| v0_8(void) = NoOp : -# 846| v0_9(void) = ReturnVoid : -# 846| v0_10(void) = UnmodeledUse : mu* -# 846| v0_11(void) = AliasedUse : ~mu0_2 -# 846| v0_12(void) = ExitFunction : +# 846| v0_0(void) = EnterFunction : +# 846| mu0_1(unknown) = AliasedDefinition : +# 846| mu0_2(unknown) = UnmodeledDefinition : +# 846| r0_3(glval) = InitializeThis : +# 846| r0_4(glval) = ConvertToNonVirtualBase[PolymorphicDerived : PolymorphicBase] : r0_3 +# 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : +# 846| v0_6(void) = Call : func:r0_5, this:r0_4 +# 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 846| v0_8(void) = NoOp : +# 846| v0_9(void) = ReturnVoid : +# 846| v0_10(void) = UnmodeledUse : mu* +# 846| v0_11(void) = AliasedUse : ~mu0_2 +# 846| v0_12(void) = ExitFunction : # 846| void PolymorphicDerived::~PolymorphicDerived() # 846| Block 0 -# 846| v0_0(void) = EnterFunction : -# 846| mu0_1(unknown) = AliasedDefinition : -# 846| mu0_2(unknown) = UnmodeledDefinition : -# 846| r0_3(glval) = InitializeThis : -#-----| v0_4(void) = NoOp : -# 846| r0_5(glval) = ConvertToBase[PolymorphicDerived : PolymorphicBase] : r0_3 -# 846| r0_6(glval) = FunctionAddress[~PolymorphicBase] : -# 846| v0_7(void) = Call : func:r0_6, this:r0_5 -# 846| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 846| v0_9(void) = ReturnVoid : -# 846| v0_10(void) = UnmodeledUse : mu* -# 846| v0_11(void) = AliasedUse : ~mu0_2 -# 846| v0_12(void) = ExitFunction : +# 846| v0_0(void) = EnterFunction : +# 846| mu0_1(unknown) = AliasedDefinition : +# 846| mu0_2(unknown) = UnmodeledDefinition : +# 846| r0_3(glval) = InitializeThis : +#-----| v0_4(void) = NoOp : +# 846| r0_5(glval) = ConvertToNonVirtualBase[PolymorphicDerived : PolymorphicBase] : r0_3 +# 846| r0_6(glval) = FunctionAddress[~PolymorphicBase] : +# 846| v0_7(void) = Call : func:r0_6, this:r0_5 +# 846| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 846| v0_9(void) = ReturnVoid : +# 846| v0_10(void) = UnmodeledUse : mu* +# 846| v0_11(void) = AliasedUse : ~mu0_2 +# 846| v0_12(void) = ExitFunction : # 849| void DynamicCast() # 849| Block 0 @@ -4027,43 +4138,47 @@ ir.cpp: # 851| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 # 853| r0_11(glval) = VariableAddress[pb] : # 853| r0_12(glval) = VariableAddress[b] : -# 853| mu0_13(PolymorphicBase *) = Store : &:r0_11, r0_12 -# 854| r0_14(glval) = VariableAddress[pd] : -# 854| r0_15(glval) = VariableAddress[d] : -# 854| mu0_16(PolymorphicDerived *) = Store : &:r0_14, r0_15 -# 857| r0_17(glval) = VariableAddress[pd] : -# 857| r0_18(PolymorphicDerived *) = Load : &:r0_17, ~mu0_2 -# 857| r0_19(PolymorphicBase *) = CheckedConvertOrNull : r0_18 -# 857| r0_20(glval) = VariableAddress[pb] : -# 857| mu0_21(PolymorphicBase *) = Store : &:r0_20, r0_19 -# 858| r0_22(glval) = VariableAddress[rb] : -# 858| r0_23(glval) = VariableAddress[d] : -# 858| r0_24(glval) = CheckedConvertOrThrow : r0_23 -# 858| mu0_25(PolymorphicBase &) = Store : &:r0_22, r0_24 -# 860| r0_26(glval) = VariableAddress[pb] : -# 860| r0_27(PolymorphicBase *) = Load : &:r0_26, ~mu0_2 -# 860| r0_28(PolymorphicDerived *) = CheckedConvertOrNull : r0_27 -# 860| r0_29(glval) = VariableAddress[pd] : -# 860| mu0_30(PolymorphicDerived *) = Store : &:r0_29, r0_28 -# 861| r0_31(glval) = VariableAddress[rd] : -# 861| r0_32(glval) = VariableAddress[b] : -# 861| r0_33(glval) = CheckedConvertOrThrow : r0_32 -# 861| mu0_34(PolymorphicDerived &) = Store : &:r0_31, r0_33 -# 863| r0_35(glval) = VariableAddress[pv] : -# 863| r0_36(glval) = VariableAddress[pb] : -# 863| r0_37(PolymorphicBase *) = Load : &:r0_36, ~mu0_2 -# 863| r0_38(void *) = DynamicCastToVoid : r0_37 -# 863| mu0_39(void *) = Store : &:r0_35, r0_38 -# 864| r0_40(glval) = VariableAddress[pcv] : -# 864| r0_41(glval) = VariableAddress[pd] : -# 864| r0_42(PolymorphicDerived *) = Load : &:r0_41, ~mu0_2 -# 864| r0_43(void *) = DynamicCastToVoid : r0_42 -# 864| mu0_44(void *) = Store : &:r0_40, r0_43 -# 865| v0_45(void) = NoOp : -# 849| v0_46(void) = ReturnVoid : -# 849| v0_47(void) = UnmodeledUse : mu* -# 849| v0_48(void) = AliasedUse : ~mu0_2 -# 849| v0_49(void) = ExitFunction : +# 853| r0_13(PolymorphicBase *) = CopyValue : r0_12 +# 853| mu0_14(PolymorphicBase *) = Store : &:r0_11, r0_13 +# 854| r0_15(glval) = VariableAddress[pd] : +# 854| r0_16(glval) = VariableAddress[d] : +# 854| r0_17(PolymorphicDerived *) = CopyValue : r0_16 +# 854| mu0_18(PolymorphicDerived *) = Store : &:r0_15, r0_17 +# 857| r0_19(glval) = VariableAddress[pd] : +# 857| r0_20(PolymorphicDerived *) = Load : &:r0_19, ~mu0_2 +# 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 +# 857| r0_22(glval) = VariableAddress[pb] : +# 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 +# 858| r0_24(glval) = VariableAddress[rb] : +# 858| r0_25(glval) = VariableAddress[d] : +# 858| r0_26(glval) = CheckedConvertOrThrow : r0_25 +# 858| r0_27(PolymorphicBase &) = CopyValue : r0_26 +# 858| mu0_28(PolymorphicBase &) = Store : &:r0_24, r0_27 +# 860| r0_29(glval) = VariableAddress[pb] : +# 860| r0_30(PolymorphicBase *) = Load : &:r0_29, ~mu0_2 +# 860| r0_31(PolymorphicDerived *) = CheckedConvertOrNull : r0_30 +# 860| r0_32(glval) = VariableAddress[pd] : +# 860| mu0_33(PolymorphicDerived *) = Store : &:r0_32, r0_31 +# 861| r0_34(glval) = VariableAddress[rd] : +# 861| r0_35(glval) = VariableAddress[b] : +# 861| r0_36(glval) = CheckedConvertOrThrow : r0_35 +# 861| r0_37(PolymorphicDerived &) = CopyValue : r0_36 +# 861| mu0_38(PolymorphicDerived &) = Store : &:r0_34, r0_37 +# 863| r0_39(glval) = VariableAddress[pv] : +# 863| r0_40(glval) = VariableAddress[pb] : +# 863| r0_41(PolymorphicBase *) = Load : &:r0_40, ~mu0_2 +# 863| r0_42(void *) = DynamicCastToVoid : r0_41 +# 863| mu0_43(void *) = Store : &:r0_39, r0_42 +# 864| r0_44(glval) = VariableAddress[pcv] : +# 864| r0_45(glval) = VariableAddress[pd] : +# 864| r0_46(PolymorphicDerived *) = Load : &:r0_45, ~mu0_2 +# 864| r0_47(void *) = DynamicCastToVoid : r0_46 +# 864| mu0_48(void *) = Store : &:r0_44, r0_47 +# 865| v0_49(void) = NoOp : +# 849| v0_50(void) = ReturnVoid : +# 849| v0_51(void) = UnmodeledUse : mu* +# 849| v0_52(void) = AliasedUse : ~mu0_2 +# 849| v0_53(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -4104,33 +4219,39 @@ ir.cpp: # 875| r0_15(char *) = Convert : r0_14 # 875| r0_16(int) = Constant[0] : # 875| r0_17(glval) = PointerAdd[1] : r0_15, r0_16 -# 875| r0_18(char *) = Convert : r0_17 -# 875| r0_19(glval) = VariableAddress[p] : -# 875| mu0_20(char *) = Store : &:r0_19, r0_18 -# 876| r0_21(glval) = StringConstant["test"] : -# 876| r0_22(char *) = Convert : r0_21 -# 876| r0_23(int) = Constant[0] : -# 876| r0_24(glval) = PointerAdd[1] : r0_22, r0_23 -# 876| r0_25(glval) = VariableAddress[p] : -# 876| mu0_26(char *) = Store : &:r0_25, r0_24 -# 877| r0_27(glval) = VariableAddress[ra] : -# 877| r0_28(glval) = VariableAddress[a] : -# 877| mu0_29(char(&)[5]) = Store : &:r0_27, r0_28 -# 878| r0_30(glval) = VariableAddress[rs] : -# 878| r0_31(glval) = StringConstant["test"] : -# 878| mu0_32(char(&)[5]) = Store : &:r0_30, r0_31 -# 879| r0_33(glval) = VariableAddress[pa] : -# 879| r0_34(glval) = VariableAddress[a] : -# 879| r0_35(char(*)[5]) = Convert : r0_34 -# 879| mu0_36(char(*)[5]) = Store : &:r0_33, r0_35 -# 880| r0_37(glval) = StringConstant["test"] : -# 880| r0_38(glval) = VariableAddress[pa] : -# 880| mu0_39(char(*)[5]) = Store : &:r0_38, r0_37 -# 881| v0_40(void) = NoOp : -# 871| v0_41(void) = ReturnVoid : -# 871| v0_42(void) = UnmodeledUse : mu* -# 871| v0_43(void) = AliasedUse : ~mu0_2 -# 871| v0_44(void) = ExitFunction : +# 875| r0_18(char *) = CopyValue : r0_17 +# 875| r0_19(char *) = Convert : r0_18 +# 875| r0_20(glval) = VariableAddress[p] : +# 875| mu0_21(char *) = Store : &:r0_20, r0_19 +# 876| r0_22(glval) = StringConstant["test"] : +# 876| r0_23(char *) = Convert : r0_22 +# 876| r0_24(int) = Constant[0] : +# 876| r0_25(glval) = PointerAdd[1] : r0_23, r0_24 +# 876| r0_26(char *) = CopyValue : r0_25 +# 876| r0_27(glval) = VariableAddress[p] : +# 876| mu0_28(char *) = Store : &:r0_27, r0_26 +# 877| r0_29(glval) = VariableAddress[ra] : +# 877| r0_30(glval) = VariableAddress[a] : +# 877| r0_31(char(&)[5]) = CopyValue : r0_30 +# 877| mu0_32(char(&)[5]) = Store : &:r0_29, r0_31 +# 878| r0_33(glval) = VariableAddress[rs] : +# 878| r0_34(glval) = StringConstant["test"] : +# 878| r0_35(char(&)[5]) = CopyValue : r0_34 +# 878| mu0_36(char(&)[5]) = Store : &:r0_33, r0_35 +# 879| r0_37(glval) = VariableAddress[pa] : +# 879| r0_38(glval) = VariableAddress[a] : +# 879| r0_39(char(*)[5]) = CopyValue : r0_38 +# 879| r0_40(char(*)[5]) = Convert : r0_39 +# 879| mu0_41(char(*)[5]) = Store : &:r0_37, r0_40 +# 880| r0_42(glval) = StringConstant["test"] : +# 880| r0_43(char(*)[5]) = CopyValue : r0_42 +# 880| r0_44(glval) = VariableAddress[pa] : +# 880| mu0_45(char(*)[5]) = Store : &:r0_44, r0_43 +# 881| v0_46(void) = NoOp : +# 871| v0_47(void) = ReturnVoid : +# 871| v0_48(void) = UnmodeledUse : mu* +# 871| v0_49(void) = AliasedUse : ~mu0_2 +# 871| v0_50(void) = ExitFunction : # 883| void FuncPtrConversions(int(*)(int), void*) # 883| Block 0 @@ -4461,7 +4582,8 @@ ir.cpp: # 967| mu0_13(bool) = Store : &:r0_7, r0_12 # 967| r0_14(glval) = VariableAddress[b] : # 967| r0_15(bool) = Load : &:r0_14, ~mu0_2 -# 967| v0_16(void) = ConditionalBranch : r0_15 +# 967| r0_16(bool) = CopyValue : r0_15 +# 967| v0_17(void) = ConditionalBranch : r0_16 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4483,7 +4605,8 @@ ir.cpp: # 970| r2_8(int) = Load : &:r2_7, ~mu0_2 # 970| r2_9(int) = Constant[0] : # 970| r2_10(bool) = CompareNE : r2_8, r2_9 -# 970| v2_11(void) = ConditionalBranch : r2_10 +# 970| r2_11(bool) = CopyValue : r2_10 +# 970| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4496,12 +4619,14 @@ ir.cpp: # 973| Block 4 # 973| r4_0(glval) = VariableAddress[p] : # 973| r4_1(glval) = VariableAddress[x] : -# 973| mu4_2(int *) = Store : &:r4_0, r4_1 -# 973| r4_3(glval) = VariableAddress[p] : -# 973| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 973| r4_5(int *) = Constant[0] : -# 973| r4_6(bool) = CompareNE : r4_4, r4_5 -# 973| v4_7(void) = ConditionalBranch : r4_6 +# 973| r4_2(int *) = CopyValue : r4_1 +# 973| mu4_3(int *) = Store : &:r4_0, r4_2 +# 973| r4_4(glval) = VariableAddress[p] : +# 973| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 973| r4_6(int *) = Constant[0] : +# 973| r4_7(bool) = CompareNE : r4_5, r4_6 +# 973| r4_8(bool) = CopyValue : r4_7 +# 973| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4509,7 +4634,8 @@ ir.cpp: # 974| r5_0(int) = Constant[2] : # 974| r5_1(glval) = VariableAddress[p] : # 974| r5_2(int *) = Load : &:r5_1, ~mu0_2 -# 974| mu5_3(int) = Store : &:r5_2, r5_0 +# 974| r5_3(glval) = CopyValue : r5_2 +# 974| mu5_4(int) = Store : &:r5_3, r5_0 #-----| Goto -> Block 6 # 976| Block 6 @@ -4546,7 +4672,8 @@ ir.cpp: # 981| r2_8(int) = Load : &:r2_7, ~mu0_2 # 981| r2_9(int) = Constant[0] : # 981| r2_10(bool) = CompareNE : r2_8, r2_9 -# 981| v2_11(void) = ConditionalBranch : r2_10 +# 981| r2_11(bool) = CopyValue : r2_10 +# 981| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4557,12 +4684,14 @@ ir.cpp: # 983| Block 4 # 983| r4_0(glval) = VariableAddress[p] : # 983| r4_1(glval) = VariableAddress[x] : -# 983| mu4_2(int *) = Store : &:r4_0, r4_1 -# 983| r4_3(glval) = VariableAddress[p] : -# 983| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 983| r4_5(int *) = Constant[0] : -# 983| r4_6(bool) = CompareNE : r4_4, r4_5 -# 983| v4_7(void) = ConditionalBranch : r4_6 +# 983| r4_2(int *) = CopyValue : r4_1 +# 983| mu4_3(int *) = Store : &:r4_0, r4_2 +# 983| r4_4(glval) = VariableAddress[p] : +# 983| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 983| r4_6(int *) = Constant[0] : +# 983| r4_7(bool) = CompareNE : r4_5, r4_6 +# 983| r4_8(bool) = CopyValue : r4_7 +# 983| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4587,7 +4716,8 @@ ir.cpp: # 979| mu7_6(bool) = Store : &:r7_0, r7_5 # 979| r7_7(glval) = VariableAddress[b] : # 979| r7_8(bool) = Load : &:r7_7, ~mu0_2 -# 979| v7_9(void) = ConditionalBranch : r7_8 +# 979| r7_9(bool) = CopyValue : r7_8 +# 979| v7_10(void) = ConditionalBranch : r7_9 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4769,164 +4899,176 @@ 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) = VariableAddress[x] : -# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 -# 1031| r0_5(glval) = VariableAddress[s] : -# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 -# 1032| r0_7(glval) = VariableAddress[lambda_empty] : -# 1032| r0_8(glval) = 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) = VariableAddress[lambda_ref] : -# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : -# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 -# 1034| r0_16(glval) = FieldAddress[s] : r0_14 -#-----| r0_17(glval) = VariableAddress[s] : -#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(String &) = Store : &:r0_16, r0_18 -# 1034| r0_20(glval) = FieldAddress[x] : r0_14 -#-----| r0_21(glval) = VariableAddress[x] : -#-----| mu0_22(int &) = Store : &:r0_20, r0_21 -# 1034| r0_23(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 -# 1034| mu0_24(decltype([...](...){...})) = Store : &:r0_13, r0_23 -# 1035| r0_25(glval) = VariableAddress[lambda_ref] : -# 1035| r0_26(glval) = Convert : r0_25 -# 1035| r0_27(glval) = FunctionAddress[operator()] : -# 1035| r0_28(float) = Constant[1.0] : -# 1035| r0_29(char) = Call : func:r0_27, this:r0_26, 0:r0_28 -# 1035| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 -# 1035| v0_31(void) = ^BufferReadSideEffect[-1] : &:r0_26, ~mu0_2 -# 1035| mu0_32(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_26 -# 1036| r0_33(glval) = VariableAddress[lambda_val] : -# 1036| r0_34(glval) = FunctionAddress[(constructor)] : -# 1036| r0_35(glval) = VariableAddress[#temp1036:21] : -# 1036| mu0_36(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_35 -# 1036| r0_37(glval) = FieldAddress[s] : r0_35 -#-----| r0_38(glval) = FunctionAddress[String] : -#-----| v0_39(void) = Call : func:r0_38, this:r0_37 -#-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_41(glval) = FieldAddress[x] : r0_35 -#-----| r0_42(glval) = VariableAddress[x] : -#-----| r0_43(int) = Load : &:r0_42, ~mu0_2 -#-----| mu0_44(int) = Store : &:r0_41, r0_43 -# 1036| r0_45(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 -# 1036| v0_46(void) = Call : func:r0_34, this:r0_33, 0:r0_45 -# 1036| mu0_47(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| v0_48(void) = ^BufferReadSideEffect[0] : &:r0_45, ~mu0_2 -# 1036| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_45 -# 1037| r0_50(glval) = VariableAddress[lambda_val] : -# 1037| r0_51(glval) = Convert : r0_50 -# 1037| r0_52(glval) = 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) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_59(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_60(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_59 -# 1038| r0_61(glval) = FieldAddress[s] : r0_59 -# 1038| r0_62(glval) = VariableAddress[s] : -# 1038| r0_63(String &) = Load : &:r0_62, ~mu0_2 -# 1038| mu0_64(String &) = Store : &:r0_61, r0_63 -# 1038| r0_65(decltype([...](...){...})) = Load : &:r0_59, ~mu0_2 -# 1038| mu0_66(decltype([...](...){...})) = Store : &:r0_58, r0_65 -# 1039| r0_67(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_68(glval) = Convert : r0_67 -# 1039| r0_69(glval) = FunctionAddress[operator()] : -# 1039| r0_70(float) = Constant[3.0] : -# 1039| r0_71(char) = Call : func:r0_69, this:r0_68, 0:r0_70 -# 1039| mu0_72(unknown) = ^CallSideEffect : ~mu0_2 -# 1039| v0_73(void) = ^BufferReadSideEffect[-1] : &:r0_68, ~mu0_2 -# 1039| mu0_74(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_68 -# 1040| r0_75(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_76(glval) = FunctionAddress[(constructor)] : -# 1040| r0_77(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_78(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_77 -# 1040| r0_79(glval) = FieldAddress[s] : r0_77 -#-----| r0_80(glval) = FunctionAddress[String] : -#-----| v0_81(void) = Call : func:r0_80, this:r0_79 -#-----| mu0_82(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_83(decltype([...](...){...})) = Load : &:r0_77, ~mu0_2 -# 1040| v0_84(void) = Call : func:r0_76, this:r0_75, 0:r0_83 -# 1040| mu0_85(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| v0_86(void) = ^BufferReadSideEffect[0] : &:r0_83, ~mu0_2 -# 1040| mu0_87(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_83 -# 1041| r0_88(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_89(glval) = Convert : r0_88 -# 1041| r0_90(glval) = FunctionAddress[operator()] : -# 1041| r0_91(float) = Constant[4.0] : -# 1041| r0_92(char) = Call : func:r0_90, this:r0_89, 0:r0_91 -# 1041| mu0_93(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| v0_94(void) = ^BufferReadSideEffect[-1] : &:r0_89, ~mu0_2 -# 1041| mu0_95(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_89 -# 1042| r0_96(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_97(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_98(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_97 -# 1042| r0_99(glval) = FieldAddress[s] : r0_97 -# 1042| r0_100(glval) = VariableAddress[s] : -# 1042| r0_101(String &) = Load : &:r0_100, ~mu0_2 -# 1042| mu0_102(String &) = Store : &:r0_99, r0_101 -# 1042| r0_103(glval) = FieldAddress[x] : r0_97 -# 1042| r0_104(glval) = VariableAddress[x] : -# 1042| r0_105(int) = Load : &:r0_104, ~mu0_2 -# 1042| mu0_106(int) = Store : &:r0_103, r0_105 -# 1042| r0_107(decltype([...](...){...})) = Load : &:r0_97, ~mu0_2 -# 1042| mu0_108(decltype([...](...){...})) = Store : &:r0_96, r0_107 -# 1043| r0_109(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_110(glval) = Convert : r0_109 -# 1043| r0_111(glval) = FunctionAddress[operator()] : -# 1043| r0_112(float) = Constant[5.0] : -# 1043| r0_113(char) = Call : func:r0_111, this:r0_110, 0:r0_112 -# 1043| mu0_114(unknown) = ^CallSideEffect : ~mu0_2 -# 1043| v0_115(void) = ^BufferReadSideEffect[-1] : &:r0_110, ~mu0_2 -# 1043| mu0_116(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 -# 1044| r0_117(glval) = VariableAddress[r] : -# 1044| r0_118(glval) = VariableAddress[x] : -# 1044| r0_119(int) = Load : &:r0_118, ~mu0_2 -# 1044| r0_120(int) = Constant[1] : -# 1044| r0_121(int) = Sub : r0_119, r0_120 -# 1044| mu0_122(int) = Store : &:r0_117, r0_121 -# 1045| r0_123(glval) = VariableAddress[lambda_inits] : -# 1045| r0_124(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_125(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_124 -# 1045| r0_126(glval) = FieldAddress[s] : r0_124 -# 1045| r0_127(glval) = VariableAddress[s] : -# 1045| r0_128(String &) = Load : &:r0_127, ~mu0_2 -# 1045| mu0_129(String &) = Store : &:r0_126, r0_128 -# 1045| r0_130(glval) = FieldAddress[x] : r0_124 -# 1045| r0_131(glval) = VariableAddress[x] : -# 1045| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 1045| mu0_133(int) = Store : &:r0_130, r0_132 -# 1045| r0_134(glval) = FieldAddress[i] : r0_124 -# 1045| r0_135(glval) = VariableAddress[x] : -# 1045| r0_136(int) = Load : &:r0_135, ~mu0_2 -# 1045| r0_137(int) = Constant[1] : -# 1045| r0_138(int) = Add : r0_136, r0_137 -# 1045| mu0_139(int) = Store : &:r0_134, r0_138 -# 1045| r0_140(glval) = FieldAddress[j] : r0_124 -# 1045| r0_141(glval) = VariableAddress[r] : -# 1045| mu0_142(int &) = Store : &:r0_140, r0_141 -# 1045| r0_143(decltype([...](...){...})) = Load : &:r0_124, ~mu0_2 -# 1045| mu0_144(decltype([...](...){...})) = Store : &:r0_123, r0_143 -# 1046| r0_145(glval) = VariableAddress[lambda_inits] : -# 1046| r0_146(glval) = Convert : r0_145 -# 1046| r0_147(glval) = FunctionAddress[operator()] : -# 1046| r0_148(float) = Constant[6.0] : -# 1046| r0_149(char) = Call : func:r0_147, this:r0_146, 0:r0_148 -# 1046| mu0_150(unknown) = ^CallSideEffect : ~mu0_2 -# 1046| v0_151(void) = ^BufferReadSideEffect[-1] : &:r0_146, ~mu0_2 -# 1046| mu0_152(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_146 -# 1047| v0_153(void) = NoOp : -# 1031| v0_154(void) = ReturnVoid : -# 1031| v0_155(void) = UnmodeledUse : mu* -# 1031| v0_156(void) = AliasedUse : ~mu0_2 -# 1031| v0_157(void) = ExitFunction : +# 1031| v0_0(void) = EnterFunction : +# 1031| mu0_1(unknown) = AliasedDefinition : +# 1031| mu0_2(unknown) = UnmodeledDefinition : +# 1031| r0_3(glval) = VariableAddress[x] : +# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 +# 1031| r0_5(glval) = VariableAddress[s] : +# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 +# 1032| r0_7(glval) = VariableAddress[lambda_empty] : +# 1032| r0_8(glval) = 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) = VariableAddress[lambda_ref] : +# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : +# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 +# 1034| r0_16(glval) = FieldAddress[s] : r0_14 +#-----| r0_17(glval) = VariableAddress[s] : +#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 +# 1034| r0_19(glval) = CopyValue : r0_18 +# 1034| r0_20(String &) = CopyValue : r0_19 +# 1034| mu0_21(String &) = Store : &:r0_16, r0_20 +# 1034| r0_22(glval) = FieldAddress[x] : r0_14 +#-----| r0_23(glval) = 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) = VariableAddress[lambda_ref] : +# 1035| r0_29(glval) = Convert : r0_28 +# 1035| r0_30(glval) = 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) = VariableAddress[lambda_val] : +# 1036| r0_37(glval) = FunctionAddress[(constructor)] : +# 1036| r0_38(glval) = VariableAddress[#temp1036:21] : +# 1036| mu0_39(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_38 +# 1036| r0_40(glval) = FieldAddress[s] : r0_38 +#-----| r0_41(glval) = FunctionAddress[String] : +#-----| v0_42(void) = Call : func:r0_41, this:r0_40 +#-----| mu0_43(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_44(glval) = FieldAddress[x] : r0_38 +#-----| r0_45(glval) = VariableAddress[x] : +#-----| r0_46(int) = Load : &:r0_45, ~mu0_2 +#-----| mu0_47(int) = Store : &:r0_44, r0_46 +# 1036| r0_48(decltype([...](...){...})) = Load : &:r0_38, ~mu0_2 +# 1036| r0_49(lambda [] type at line 1036, col. 21 &) = CopyValue : r0_48 +# 1036| v0_50(void) = Call : func:r0_37, this:r0_36, 0:r0_49 +# 1036| mu0_51(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| v0_52(void) = ^BufferReadSideEffect[0] : &:r0_49, ~mu0_2 +# 1036| mu0_53(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_49 +# 1037| r0_54(glval) = VariableAddress[lambda_val] : +# 1037| r0_55(glval) = Convert : r0_54 +# 1037| r0_56(glval) = FunctionAddress[operator()] : +# 1037| r0_57(float) = Constant[2.0] : +# 1037| r0_58(char) = Call : func:r0_56, this:r0_55, 0:r0_57 +# 1037| mu0_59(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| v0_60(void) = ^BufferReadSideEffect[-1] : &:r0_55, ~mu0_2 +# 1037| mu0_61(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_55 +# 1038| r0_62(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_63(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_64(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_63 +# 1038| r0_65(glval) = FieldAddress[s] : r0_63 +# 1038| r0_66(glval) = VariableAddress[s] : +# 1038| r0_67(String &) = Load : &:r0_66, ~mu0_2 +# 1038| r0_68(glval) = CopyValue : r0_67 +# 1038| r0_69(String &) = CopyValue : r0_68 +# 1038| mu0_70(String &) = Store : &:r0_65, r0_69 +# 1038| r0_71(decltype([...](...){...})) = Load : &:r0_63, ~mu0_2 +# 1038| mu0_72(decltype([...](...){...})) = Store : &:r0_62, r0_71 +# 1039| r0_73(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_74(glval) = Convert : r0_73 +# 1039| r0_75(glval) = FunctionAddress[operator()] : +# 1039| r0_76(float) = Constant[3.0] : +# 1039| r0_77(char) = Call : func:r0_75, this:r0_74, 0:r0_76 +# 1039| mu0_78(unknown) = ^CallSideEffect : ~mu0_2 +# 1039| v0_79(void) = ^BufferReadSideEffect[-1] : &:r0_74, ~mu0_2 +# 1039| mu0_80(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_74 +# 1040| r0_81(glval) = VariableAddress[lambda_val_explicit] : +# 1040| r0_82(glval) = FunctionAddress[(constructor)] : +# 1040| r0_83(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_84(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_83 +# 1040| r0_85(glval) = FieldAddress[s] : r0_83 +#-----| r0_86(glval) = FunctionAddress[String] : +#-----| v0_87(void) = Call : func:r0_86, this:r0_85 +#-----| mu0_88(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_89(decltype([...](...){...})) = Load : &:r0_83, ~mu0_2 +# 1040| r0_90(lambda [] type at line 1040, col. 30 &) = CopyValue : r0_89 +# 1040| v0_91(void) = Call : func:r0_82, this:r0_81, 0:r0_90 +# 1040| mu0_92(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| v0_93(void) = ^BufferReadSideEffect[0] : &:r0_90, ~mu0_2 +# 1040| mu0_94(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_90 +# 1041| r0_95(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_96(glval) = Convert : r0_95 +# 1041| r0_97(glval) = FunctionAddress[operator()] : +# 1041| r0_98(float) = Constant[4.0] : +# 1041| r0_99(char) = Call : func:r0_97, this:r0_96, 0:r0_98 +# 1041| mu0_100(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| v0_101(void) = ^BufferReadSideEffect[-1] : &:r0_96, ~mu0_2 +# 1041| mu0_102(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_96 +# 1042| r0_103(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_104(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_105(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_104 +# 1042| r0_106(glval) = FieldAddress[s] : r0_104 +# 1042| r0_107(glval) = VariableAddress[s] : +# 1042| r0_108(String &) = Load : &:r0_107, ~mu0_2 +# 1042| r0_109(glval) = CopyValue : r0_108 +# 1042| r0_110(String &) = CopyValue : r0_109 +# 1042| mu0_111(String &) = Store : &:r0_106, r0_110 +# 1042| r0_112(glval) = FieldAddress[x] : r0_104 +# 1042| r0_113(glval) = VariableAddress[x] : +# 1042| r0_114(int) = Load : &:r0_113, ~mu0_2 +# 1042| mu0_115(int) = Store : &:r0_112, r0_114 +# 1042| r0_116(decltype([...](...){...})) = Load : &:r0_104, ~mu0_2 +# 1042| mu0_117(decltype([...](...){...})) = Store : &:r0_103, r0_116 +# 1043| r0_118(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_119(glval) = Convert : r0_118 +# 1043| r0_120(glval) = FunctionAddress[operator()] : +# 1043| r0_121(float) = Constant[5.0] : +# 1043| r0_122(char) = Call : func:r0_120, this:r0_119, 0:r0_121 +# 1043| mu0_123(unknown) = ^CallSideEffect : ~mu0_2 +# 1043| v0_124(void) = ^BufferReadSideEffect[-1] : &:r0_119, ~mu0_2 +# 1043| mu0_125(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_119 +# 1044| r0_126(glval) = VariableAddress[r] : +# 1044| r0_127(glval) = VariableAddress[x] : +# 1044| r0_128(int) = Load : &:r0_127, ~mu0_2 +# 1044| r0_129(int) = Constant[1] : +# 1044| r0_130(int) = Sub : r0_128, r0_129 +# 1044| mu0_131(int) = Store : &:r0_126, r0_130 +# 1045| r0_132(glval) = VariableAddress[lambda_inits] : +# 1045| r0_133(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_134(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_133 +# 1045| r0_135(glval) = FieldAddress[s] : r0_133 +# 1045| r0_136(glval) = VariableAddress[s] : +# 1045| r0_137(String &) = Load : &:r0_136, ~mu0_2 +# 1045| r0_138(glval) = CopyValue : r0_137 +# 1045| r0_139(String &) = CopyValue : r0_138 +# 1045| mu0_140(String &) = Store : &:r0_135, r0_139 +# 1045| r0_141(glval) = FieldAddress[x] : r0_133 +# 1045| r0_142(glval) = VariableAddress[x] : +# 1045| r0_143(int) = Load : &:r0_142, ~mu0_2 +# 1045| mu0_144(int) = Store : &:r0_141, r0_143 +# 1045| r0_145(glval) = FieldAddress[i] : r0_133 +# 1045| r0_146(glval) = VariableAddress[x] : +# 1045| r0_147(int) = Load : &:r0_146, ~mu0_2 +# 1045| r0_148(int) = Constant[1] : +# 1045| r0_149(int) = Add : r0_147, r0_148 +# 1045| mu0_150(int) = Store : &:r0_145, r0_149 +# 1045| r0_151(glval) = FieldAddress[j] : r0_133 +# 1045| r0_152(glval) = VariableAddress[r] : +# 1045| r0_153(int &) = CopyValue : r0_152 +# 1045| mu0_154(int &) = Store : &:r0_151, r0_153 +# 1045| r0_155(decltype([...](...){...})) = Load : &:r0_133, ~mu0_2 +# 1045| mu0_156(decltype([...](...){...})) = Store : &:r0_132, r0_155 +# 1046| r0_157(glval) = VariableAddress[lambda_inits] : +# 1046| r0_158(glval) = Convert : r0_157 +# 1046| r0_159(glval) = FunctionAddress[operator()] : +# 1046| r0_160(float) = Constant[6.0] : +# 1046| r0_161(char) = Call : func:r0_159, this:r0_158, 0:r0_160 +# 1046| mu0_162(unknown) = ^CallSideEffect : ~mu0_2 +# 1046| v0_163(void) = ^BufferReadSideEffect[-1] : &:r0_158, ~mu0_2 +# 1046| mu0_164(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_158 +# 1047| v0_165(void) = NoOp : +# 1031| v0_166(void) = ReturnVoid : +# 1031| v0_167(void) = UnmodeledUse : mu* +# 1031| v0_168(void) = AliasedUse : ~mu0_2 +# 1031| v0_169(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 @@ -4986,23 +5128,24 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1034| r0_10(glval) = FunctionAddress[c_str] : -# 1034| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1034| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1034| v0_13(void) = ^BufferReadSideEffect[-1] : &:r0_9, ~mu0_2 -# 1034| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 -#-----| r0_15(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 -#-----| r0_16(glval) = FieldAddress[x] : r0_15 -#-----| r0_17(int &) = Load : &:r0_16, ~mu0_2 -# 1034| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 1034| r0_19(glval) = PointerAdd[1] : r0_11, r0_18 -# 1034| r0_20(char) = Load : &:r0_19, ~mu0_2 -# 1034| mu0_21(char) = Store : &:r0_6, r0_20 -# 1034| r0_22(glval) = VariableAddress[#return] : -# 1034| v0_23(void) = ReturnValue : &:r0_22, ~mu0_2 -# 1034| v0_24(void) = UnmodeledUse : mu* -# 1034| v0_25(void) = AliasedUse : ~mu0_2 -# 1034| v0_26(void) = ExitFunction : +# 1034| r0_10(glval) = CopyValue : r0_9 +# 1034| r0_11(glval) = FunctionAddress[c_str] : +# 1034| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1034| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1034| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2 +# 1034| mu0_15(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +#-----| r0_16(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 +#-----| r0_17(glval) = FieldAddress[x] : r0_16 +#-----| r0_18(int &) = Load : &:r0_17, ~mu0_2 +# 1034| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 1034| r0_20(glval) = PointerAdd[1] : r0_12, r0_19 +# 1034| r0_21(char) = Load : &:r0_20, ~mu0_2 +# 1034| mu0_22(char) = Store : &:r0_6, r0_21 +# 1034| r0_23(glval) = VariableAddress[#return] : +# 1034| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 +# 1034| v0_25(void) = UnmodeledUse : mu* +# 1034| v0_26(void) = AliasedUse : ~mu0_2 +# 1034| v0_27(void) = ExitFunction : # 1036| void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::~() # 1036| Block 0 @@ -5060,20 +5203,21 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1038, col. 30 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1038| r0_10(glval) = FunctionAddress[c_str] : -# 1038| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1038| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1038| v0_13(void) = ^BufferReadSideEffect[-1] : &:r0_9, ~mu0_2 -# 1038| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 -# 1038| r0_15(int) = Constant[0] : -# 1038| r0_16(glval) = PointerAdd[1] : r0_11, r0_15 -# 1038| r0_17(char) = Load : &:r0_16, ~mu0_2 -# 1038| mu0_18(char) = Store : &:r0_6, r0_17 -# 1038| r0_19(glval) = VariableAddress[#return] : -# 1038| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 1038| v0_21(void) = UnmodeledUse : mu* -# 1038| v0_22(void) = AliasedUse : ~mu0_2 -# 1038| v0_23(void) = ExitFunction : +# 1038| r0_10(glval) = CopyValue : r0_9 +# 1038| r0_11(glval) = FunctionAddress[c_str] : +# 1038| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1038| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1038| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2 +# 1038| mu0_15(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +# 1038| r0_16(int) = Constant[0] : +# 1038| r0_17(glval) = PointerAdd[1] : r0_12, r0_16 +# 1038| r0_18(char) = Load : &:r0_17, ~mu0_2 +# 1038| mu0_19(char) = Store : &:r0_6, r0_18 +# 1038| r0_20(glval) = VariableAddress[#return] : +# 1038| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 1038| v0_22(void) = UnmodeledUse : mu* +# 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 @@ -5147,22 +5291,23 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1042| r0_10(glval) = FunctionAddress[c_str] : -# 1042| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1042| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1042| v0_13(void) = ^BufferReadSideEffect[-1] : &:r0_9, ~mu0_2 -# 1042| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 -#-----| r0_15(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 -#-----| r0_16(glval) = FieldAddress[x] : r0_15 -#-----| r0_17(int) = Load : &:r0_16, ~mu0_2 -# 1042| r0_18(glval) = PointerAdd[1] : r0_11, r0_17 -# 1042| r0_19(char) = Load : &:r0_18, ~mu0_2 -# 1042| mu0_20(char) = Store : &:r0_6, r0_19 -# 1042| r0_21(glval) = VariableAddress[#return] : -# 1042| v0_22(void) = ReturnValue : &:r0_21, ~mu0_2 -# 1042| v0_23(void) = UnmodeledUse : mu* -# 1042| v0_24(void) = AliasedUse : ~mu0_2 -# 1042| v0_25(void) = ExitFunction : +# 1042| r0_10(glval) = CopyValue : r0_9 +# 1042| r0_11(glval) = FunctionAddress[c_str] : +# 1042| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1042| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1042| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2 +# 1042| mu0_15(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +#-----| r0_16(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 +#-----| r0_17(glval) = FieldAddress[x] : r0_16 +#-----| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 1042| r0_19(glval) = PointerAdd[1] : r0_12, r0_18 +# 1042| r0_20(char) = Load : &:r0_19, ~mu0_2 +# 1042| mu0_21(char) = Store : &:r0_6, r0_20 +# 1042| r0_22(glval) = VariableAddress[#return] : +# 1042| v0_23(void) = ReturnValue : &:r0_22, ~mu0_2 +# 1042| v0_24(void) = UnmodeledUse : mu* +# 1042| v0_25(void) = AliasedUse : ~mu0_2 +# 1042| v0_26(void) = ExitFunction : # 1045| char (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::operator()(float) const # 1045| Block 0 @@ -5176,31 +5321,32 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1045| r0_10(glval) = FunctionAddress[c_str] : -# 1045| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1045| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1045| v0_13(void) = ^BufferReadSideEffect[-1] : &:r0_9, ~mu0_2 -# 1045| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 -#-----| r0_15(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -#-----| r0_16(glval) = FieldAddress[x] : r0_15 -#-----| r0_17(int) = Load : &:r0_16, ~mu0_2 -#-----| r0_18(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_19(glval) = FieldAddress[i] : r0_18 -# 1045| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 1045| r0_21(int) = Add : r0_17, r0_20 -#-----| r0_22(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_23(glval) = FieldAddress[j] : r0_22 -# 1045| r0_24(int &) = Load : &:r0_23, ~mu0_2 -# 1045| r0_25(int) = Load : &:r0_24, ~mu0_2 -# 1045| r0_26(int) = Sub : r0_21, r0_25 -# 1045| r0_27(glval) = PointerAdd[1] : r0_11, r0_26 -# 1045| r0_28(char) = Load : &:r0_27, ~mu0_2 -# 1045| mu0_29(char) = Store : &:r0_6, r0_28 -# 1045| r0_30(glval) = VariableAddress[#return] : -# 1045| v0_31(void) = ReturnValue : &:r0_30, ~mu0_2 -# 1045| v0_32(void) = UnmodeledUse : mu* -# 1045| v0_33(void) = AliasedUse : ~mu0_2 -# 1045| v0_34(void) = ExitFunction : +# 1045| r0_10(glval) = CopyValue : r0_9 +# 1045| r0_11(glval) = FunctionAddress[c_str] : +# 1045| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1045| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1045| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2 +# 1045| mu0_15(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +#-----| r0_16(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +#-----| r0_17(glval) = FieldAddress[x] : r0_16 +#-----| r0_18(int) = Load : &:r0_17, ~mu0_2 +#-----| r0_19(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_20(glval) = FieldAddress[i] : r0_19 +# 1045| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 1045| r0_22(int) = Add : r0_18, r0_21 +#-----| r0_23(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_24(glval) = FieldAddress[j] : r0_23 +# 1045| r0_25(int &) = Load : &:r0_24, ~mu0_2 +# 1045| r0_26(int) = Load : &:r0_25, ~mu0_2 +# 1045| r0_27(int) = Sub : r0_22, r0_26 +# 1045| r0_28(glval) = PointerAdd[1] : r0_12, r0_27 +# 1045| r0_29(char) = Load : &:r0_28, ~mu0_2 +# 1045| mu0_30(char) = Store : &:r0_6, r0_29 +# 1045| r0_31(glval) = VariableAddress[#return] : +# 1045| v0_32(void) = ReturnValue : &:r0_31, ~mu0_2 +# 1045| v0_33(void) = UnmodeledUse : mu* +# 1045| v0_34(void) = AliasedUse : ~mu0_2 +# 1045| v0_35(void) = ExitFunction : # 1068| void RangeBasedFor(vector const&) # 1068| Block 0 @@ -5212,153 +5358,165 @@ ir.cpp: # 1069| r0_5(glval &>) = VariableAddress[(__range)] : # 1069| r0_6(glval &>) = VariableAddress[v] : # 1069| r0_7(vector &) = Load : &:r0_6, ~mu0_2 -# 1069| mu0_8(vector &) = Store : &:r0_5, r0_7 -# 1069| r0_9(glval) = VariableAddress[(__begin)] : -#-----| r0_10(glval &>) = VariableAddress[(__range)] : -#-----| r0_11(vector &) = Load : &:r0_10, ~mu0_2 -# 1069| r0_12(glval) = FunctionAddress[begin] : -# 1069| r0_13(iterator) = Call : func:r0_12, this:r0_11 -# 1069| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_15(void) = ^BufferReadSideEffect[-1] : &:r0_11, ~mu0_2 -#-----| mu0_16(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -# 1069| mu0_17(iterator) = Store : &:r0_9, r0_13 -# 1069| r0_18(glval) = VariableAddress[(__end)] : -#-----| r0_19(glval &>) = VariableAddress[(__range)] : -#-----| r0_20(vector &) = Load : &:r0_19, ~mu0_2 -# 1069| r0_21(glval) = FunctionAddress[end] : -# 1069| r0_22(iterator) = Call : func:r0_21, this:r0_20 -# 1069| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_24(void) = ^BufferReadSideEffect[-1] : &:r0_20, ~mu0_2 -#-----| mu0_25(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_20 -# 1069| mu0_26(iterator) = Store : &:r0_18, r0_22 -#-----| Goto -> Block 4 +# 1069| r0_8(glval>) = CopyValue : r0_7 +# 1069| r0_9(vector &) = CopyValue : r0_8 +# 1069| mu0_10(vector &) = Store : &:r0_5, r0_9 +# 1069| r0_11(glval) = VariableAddress[(__begin)] : +#-----| r0_12(glval &>) = VariableAddress[(__range)] : +#-----| r0_13(vector &) = Load : &:r0_12, ~mu0_2 +#-----| r0_14(glval>) = CopyValue : r0_13 +# 1069| r0_15(glval) = FunctionAddress[begin] : +# 1069| r0_16(iterator) = Call : func:r0_15, this:r0_14 +# 1069| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_18(void) = ^BufferReadSideEffect[-1] : &:r0_14, ~mu0_2 +#-----| mu0_19(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_14 +# 1069| mu0_20(iterator) = Store : &:r0_11, r0_16 +# 1069| r0_21(glval) = VariableAddress[(__end)] : +#-----| r0_22(glval &>) = VariableAddress[(__range)] : +#-----| r0_23(vector &) = Load : &:r0_22, ~mu0_2 +#-----| r0_24(glval>) = CopyValue : r0_23 +# 1069| r0_25(glval) = FunctionAddress[end] : +# 1069| r0_26(iterator) = Call : func:r0_25, this:r0_24 +# 1069| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_28(void) = ^BufferReadSideEffect[-1] : &:r0_24, ~mu0_2 +#-----| mu0_29(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 +# 1069| mu0_30(iterator) = Store : &:r0_21, r0_26 +#-----| Goto -> Block 6 -# 1075| Block 1 -# 1075| r1_0(glval) = VariableAddress[e] : -#-----| r1_1(glval) = VariableAddress[(__begin)] : -#-----| r1_2(glval) = Convert : r1_1 -# 1075| r1_3(glval) = FunctionAddress[operator*] : -# 1075| r1_4(int &) = Call : func:r1_3, this:r1_2 -# 1075| mu1_5(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v1_6(void) = ^BufferReadSideEffect[-1] : &:r1_2, ~mu0_2 -#-----| mu1_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1_2 -# 1075| r1_8(glval) = Convert : r1_4 -# 1075| mu1_9(int &) = Store : &:r1_0, r1_8 -# 1076| r1_10(glval) = VariableAddress[e] : -# 1076| r1_11(int &) = Load : &:r1_10, ~mu0_2 -# 1076| r1_12(int) = Load : &:r1_11, ~mu0_2 -# 1076| r1_13(int) = Constant[5] : -# 1076| r1_14(bool) = CompareLT : r1_12, r1_13 -# 1076| v1_15(void) = ConditionalBranch : r1_14 +#-----| Block 1 +#-----| r1_0(glval) = VariableAddress[(__begin)] : +#-----| r1_1(glval) = Convert : r1_0 +# 1075| r1_2(glval) = FunctionAddress[operator!=] : +#-----| r1_3(glval) = VariableAddress[(__end)] : +#-----| r1_4(iterator) = Load : &:r1_3, ~mu0_2 +# 1075| r1_5(bool) = Call : func:r1_2, this:r1_1, 0:r1_4 +# 1075| mu1_6(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v1_7(void) = ^BufferReadSideEffect[-1] : &:r1_1, ~mu0_2 +#-----| mu1_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1_1 +# 1075| v1_9(void) = ConditionalBranch : r1_5 +#-----| False -> Block 5 +#-----| True -> Block 3 + +#-----| Block 2 +#-----| r2_0(glval) = VariableAddress[(__begin)] : +# 1075| r2_1(glval) = FunctionAddress[operator++] : +# 1075| r2_2(iterator &) = Call : func:r2_1, this:r2_0 +# 1075| mu2_3(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v2_4(void) = ^BufferReadSideEffect[-1] : &:r2_0, ~mu0_2 +#-----| mu2_5(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2_0 +# 1075| r2_6(glval) = CopyValue : r2_2 +#-----| Goto (back edge) -> Block 1 + +# 1075| Block 3 +# 1075| r3_0(glval) = VariableAddress[e] : +#-----| r3_1(glval) = VariableAddress[(__begin)] : +#-----| r3_2(glval) = Convert : r3_1 +# 1075| r3_3(glval) = FunctionAddress[operator*] : +# 1075| r3_4(int &) = Call : func:r3_3, this:r3_2 +# 1075| mu3_5(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v3_6(void) = ^BufferReadSideEffect[-1] : &:r3_2, ~mu0_2 +#-----| mu3_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r3_2 +# 1075| r3_8(glval) = CopyValue : r3_4 +# 1075| r3_9(glval) = Convert : r3_8 +# 1075| r3_10(int &) = CopyValue : r3_9 +# 1075| mu3_11(int &) = Store : &:r3_0, r3_10 +# 1076| r3_12(glval) = VariableAddress[e] : +# 1076| r3_13(int &) = Load : &:r3_12, ~mu0_2 +# 1076| r3_14(int) = Load : &:r3_13, ~mu0_2 +# 1076| r3_15(int) = Constant[5] : +# 1076| r3_16(bool) = CompareLT : r3_14, r3_15 +# 1076| v3_17(void) = ConditionalBranch : r3_16 +#-----| False -> Block 2 +#-----| True -> Block 4 + +# 1077| Block 4 +# 1077| v4_0(void) = NoOp : +#-----| Goto -> Block 5 + +# 1079| Block 5 +# 1079| v5_0(void) = NoOp : +# 1080| v5_1(void) = NoOp : +# 1068| v5_2(void) = ReturnVoid : +# 1068| v5_3(void) = UnmodeledUse : mu* +# 1068| v5_4(void) = AliasedUse : ~mu0_2 +# 1068| v5_5(void) = ExitFunction : + +#-----| Block 6 +#-----| r6_0(glval) = VariableAddress[(__begin)] : +#-----| r6_1(glval) = Convert : r6_0 +# 1069| r6_2(glval) = FunctionAddress[operator!=] : +#-----| r6_3(glval) = VariableAddress[(__end)] : +#-----| r6_4(iterator) = Load : &:r6_3, ~mu0_2 +# 1069| r6_5(bool) = Call : func:r6_2, this:r6_1, 0:r6_4 +# 1069| mu6_6(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v6_7(void) = ^BufferReadSideEffect[-1] : &:r6_1, ~mu0_2 +#-----| mu6_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r6_1 +# 1069| v6_9(void) = ConditionalBranch : r6_5 #-----| False -> Block 10 -#-----| True -> Block 2 - -# 1077| Block 2 -# 1077| v2_0(void) = NoOp : -#-----| Goto -> Block 3 - -# 1079| Block 3 -# 1079| v3_0(void) = NoOp : -# 1080| v3_1(void) = NoOp : -# 1068| v3_2(void) = ReturnVoid : -# 1068| v3_3(void) = UnmodeledUse : mu* -# 1068| v3_4(void) = AliasedUse : ~mu0_2 -# 1068| v3_5(void) = ExitFunction : - -#-----| Block 4 -#-----| r4_0(glval) = VariableAddress[(__begin)] : -#-----| r4_1(glval) = Convert : r4_0 -# 1069| r4_2(glval) = FunctionAddress[operator!=] : -#-----| r4_3(glval) = VariableAddress[(__end)] : -#-----| r4_4(iterator) = Load : &:r4_3, ~mu0_2 -# 1069| r4_5(bool) = Call : func:r4_2, this:r4_1, 0:r4_4 -# 1069| mu4_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v4_7(void) = ^BufferReadSideEffect[-1] : &:r4_1, ~mu0_2 -#-----| mu4_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r4_1 -# 1069| v4_9(void) = ConditionalBranch : r4_5 -#-----| False -> Block 8 -#-----| True -> Block 5 - -# 1069| Block 5 -# 1069| r5_0(glval) = VariableAddress[e] : -#-----| r5_1(glval) = VariableAddress[(__begin)] : -#-----| r5_2(glval) = Convert : r5_1 -# 1069| r5_3(glval) = FunctionAddress[operator*] : -# 1069| r5_4(int &) = Call : func:r5_3, this:r5_2 -# 1069| mu5_5(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v5_6(void) = ^BufferReadSideEffect[-1] : &:r5_2, ~mu0_2 -#-----| mu5_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r5_2 -# 1069| r5_8(int) = Load : &:r5_4, ~mu0_2 -# 1069| mu5_9(int) = Store : &:r5_0, r5_8 -# 1070| r5_10(glval) = VariableAddress[e] : -# 1070| r5_11(int) = Load : &:r5_10, ~mu0_2 -# 1070| r5_12(int) = Constant[0] : -# 1070| r5_13(bool) = CompareGT : r5_11, r5_12 -# 1070| v5_14(void) = ConditionalBranch : r5_13 -#-----| False -> Block 7 -#-----| True -> Block 6 - -# 1071| Block 6 -# 1071| v6_0(void) = NoOp : -#-----| Goto -> Block 7 +#-----| True -> Block 7 # 1069| Block 7 -# 1069| v7_0(void) = NoOp : +# 1069| r7_0(glval) = VariableAddress[e] : #-----| r7_1(glval) = VariableAddress[(__begin)] : -# 1069| r7_2(glval) = FunctionAddress[operator++] : -# 1069| r7_3(iterator &) = Call : func:r7_2, this:r7_1 -# 1069| mu7_4(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v7_5(void) = ^BufferReadSideEffect[-1] : &:r7_1, ~mu0_2 -#-----| mu7_6(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r7_1 -#-----| Goto (back edge) -> Block 4 +#-----| r7_2(glval) = Convert : r7_1 +# 1069| r7_3(glval) = FunctionAddress[operator*] : +# 1069| r7_4(int &) = Call : func:r7_3, this:r7_2 +# 1069| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v7_6(void) = ^BufferReadSideEffect[-1] : &:r7_2, ~mu0_2 +#-----| mu7_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r7_2 +# 1069| r7_8(int) = Load : &:r7_4, ~mu0_2 +# 1069| mu7_9(int) = Store : &:r7_0, r7_8 +# 1070| r7_10(glval) = VariableAddress[e] : +# 1070| r7_11(int) = Load : &:r7_10, ~mu0_2 +# 1070| r7_12(int) = Constant[0] : +# 1070| r7_13(bool) = CompareGT : r7_11, r7_12 +# 1070| v7_14(void) = ConditionalBranch : r7_13 +#-----| False -> Block 9 +#-----| True -> Block 8 -# 1075| Block 8 -# 1075| r8_0(glval &>) = VariableAddress[(__range)] : -# 1075| r8_1(glval &>) = VariableAddress[v] : -# 1075| r8_2(vector &) = Load : &:r8_1, ~mu0_2 -# 1075| mu8_3(vector &) = Store : &:r8_0, r8_2 -# 1075| r8_4(glval) = VariableAddress[(__begin)] : -#-----| r8_5(glval &>) = VariableAddress[(__range)] : -#-----| r8_6(vector &) = Load : &:r8_5, ~mu0_2 -# 1075| r8_7(glval) = FunctionAddress[begin] : -# 1075| r8_8(iterator) = Call : func:r8_7, this:r8_6 -# 1075| mu8_9(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v8_10(void) = ^BufferReadSideEffect[-1] : &:r8_6, ~mu0_2 -#-----| mu8_11(vector) = ^IndirectMayWriteSideEffect[-1] : &:r8_6 -# 1075| mu8_12(iterator) = Store : &:r8_4, r8_8 -# 1075| r8_13(glval) = VariableAddress[(__end)] : -#-----| r8_14(glval &>) = VariableAddress[(__range)] : -#-----| r8_15(vector &) = Load : &:r8_14, ~mu0_2 -# 1075| r8_16(glval) = FunctionAddress[end] : -# 1075| r8_17(iterator) = Call : func:r8_16, this:r8_15 -# 1075| mu8_18(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v8_19(void) = ^BufferReadSideEffect[-1] : &:r8_15, ~mu0_2 -#-----| mu8_20(vector) = ^IndirectMayWriteSideEffect[-1] : &:r8_15 -# 1075| mu8_21(iterator) = Store : &:r8_13, r8_17 +# 1071| Block 8 +# 1071| v8_0(void) = NoOp : #-----| Goto -> Block 9 -#-----| Block 9 -#-----| r9_0(glval) = VariableAddress[(__begin)] : -#-----| r9_1(glval) = Convert : r9_0 -# 1075| r9_2(glval) = FunctionAddress[operator!=] : -#-----| r9_3(glval) = VariableAddress[(__end)] : -#-----| r9_4(iterator) = Load : &:r9_3, ~mu0_2 -# 1075| r9_5(bool) = Call : func:r9_2, this:r9_1, 0:r9_4 -# 1075| mu9_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v9_7(void) = ^BufferReadSideEffect[-1] : &:r9_1, ~mu0_2 -#-----| mu9_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r9_1 -# 1075| v9_9(void) = ConditionalBranch : r9_5 -#-----| False -> Block 3 -#-----| True -> Block 1 +# 1069| Block 9 +# 1069| v9_0(void) = NoOp : +#-----| r9_1(glval) = VariableAddress[(__begin)] : +# 1069| r9_2(glval) = FunctionAddress[operator++] : +# 1069| r9_3(iterator &) = Call : func:r9_2, this:r9_1 +# 1069| mu9_4(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v9_5(void) = ^BufferReadSideEffect[-1] : &:r9_1, ~mu0_2 +#-----| mu9_6(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r9_1 +# 1069| r9_7(glval) = CopyValue : r9_3 +#-----| Goto (back edge) -> Block 6 -#-----| Block 10 -#-----| r10_0(glval) = VariableAddress[(__begin)] : -# 1075| r10_1(glval) = FunctionAddress[operator++] : -# 1075| r10_2(iterator &) = Call : func:r10_1, this:r10_0 -# 1075| mu10_3(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v10_4(void) = ^BufferReadSideEffect[-1] : &:r10_0, ~mu0_2 -#-----| mu10_5(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r10_0 -#-----| Goto (back edge) -> Block 9 +# 1075| Block 10 +# 1075| r10_0(glval &>) = VariableAddress[(__range)] : +# 1075| r10_1(glval &>) = VariableAddress[v] : +# 1075| r10_2(vector &) = Load : &:r10_1, ~mu0_2 +# 1075| r10_3(glval>) = CopyValue : r10_2 +# 1075| r10_4(vector &) = CopyValue : r10_3 +# 1075| mu10_5(vector &) = Store : &:r10_0, r10_4 +# 1075| r10_6(glval) = VariableAddress[(__begin)] : +#-----| r10_7(glval &>) = VariableAddress[(__range)] : +#-----| r10_8(vector &) = Load : &:r10_7, ~mu0_2 +#-----| r10_9(glval>) = CopyValue : r10_8 +# 1075| r10_10(glval) = FunctionAddress[begin] : +# 1075| r10_11(iterator) = Call : func:r10_10, this:r10_9 +# 1075| mu10_12(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v10_13(void) = ^BufferReadSideEffect[-1] : &:r10_9, ~mu0_2 +#-----| mu10_14(vector) = ^IndirectMayWriteSideEffect[-1] : &:r10_9 +# 1075| mu10_15(iterator) = Store : &:r10_6, r10_11 +# 1075| r10_16(glval) = VariableAddress[(__end)] : +#-----| r10_17(glval &>) = VariableAddress[(__range)] : +#-----| r10_18(vector &) = Load : &:r10_17, ~mu0_2 +#-----| r10_19(glval>) = CopyValue : r10_18 +# 1075| r10_20(glval) = FunctionAddress[end] : +# 1075| r10_21(iterator) = Call : func:r10_20, this:r10_19 +# 1075| mu10_22(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v10_23(void) = ^BufferReadSideEffect[-1] : &:r10_19, ~mu0_2 +#-----| mu10_24(vector) = ^IndirectMayWriteSideEffect[-1] : &:r10_19 +# 1075| mu10_25(iterator) = Store : &:r10_16, r10_21 +#-----| Goto -> Block 1 # 1099| int AsmStmt(int) # 1099| Block 0 @@ -5393,18 +5551,19 @@ ir.cpp: # 1104| mu0_10(unsigned int) = InitializeParameter[d] : &:r0_9 # 1109| r0_11(glval) = VariableAddress[a] : # 1109| r0_12(unsigned int &) = Load : &:r0_11, ~mu0_2 -# 1109| r0_13(glval) = VariableAddress[b] : -# 1109| r0_14(glval) = VariableAddress[c] : -# 1109| r0_15(unsigned int &) = Load : &:r0_14, ~mu0_2 -# 1109| r0_16(unsigned int) = Load : &:r0_15, ~mu0_2 -# 1109| r0_17(glval) = VariableAddress[d] : -# 1109| r0_18(unsigned int) = Load : &:r0_17, ~mu0_2 -# 1106| mu0_19(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_13, 2:r0_16, 3:r0_18 -# 1111| v0_20(void) = NoOp : -# 1104| v0_21(void) = ReturnVoid : -# 1104| v0_22(void) = UnmodeledUse : mu* -# 1104| v0_23(void) = AliasedUse : ~mu0_2 -# 1104| v0_24(void) = ExitFunction : +# 1109| r0_13(glval) = CopyValue : r0_12 +# 1109| r0_14(glval) = VariableAddress[b] : +# 1109| r0_15(glval) = VariableAddress[c] : +# 1109| r0_16(unsigned int &) = Load : &:r0_15, ~mu0_2 +# 1109| r0_17(unsigned int) = Load : &:r0_16, ~mu0_2 +# 1109| r0_18(glval) = VariableAddress[d] : +# 1109| r0_19(unsigned int) = Load : &:r0_18, ~mu0_2 +# 1106| mu0_20(unknown) = InlineAsm : ~mu0_2, 0:r0_13, 1:r0_14, 2:r0_17, 3:r0_19 +# 1111| v0_21(void) = NoOp : +# 1104| v0_22(void) = ReturnVoid : +# 1104| v0_23(void) = UnmodeledUse : mu* +# 1104| v0_24(void) = AliasedUse : ~mu0_2 +# 1104| v0_25(void) = ExitFunction : # 1113| void ExternDeclarations() # 1113| Block 0 @@ -5644,22 +5803,24 @@ ir.cpp: # 1164| mu0_6(int) = Uninitialized[y] : &:r0_5 # 1165| r0_7(glval) = FunctionAddress[memcpy] : # 1165| r0_8(glval) = VariableAddress[y] : -# 1165| r0_9(void *) = Convert : r0_8 -# 1165| r0_10(glval) = VariableAddress[x] : -# 1165| r0_11(void *) = Convert : r0_10 -# 1165| r0_12(int) = Constant[4] : -# 1165| r0_13(void *) = Call : func:r0_7, 0:r0_9, 1:r0_11, 2:r0_12 -# 1165| v0_14(void) = ^SizedBufferReadSideEffect[1] : &:r0_11, r0_12, ~mu0_2 -# 1165| mu0_15(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_9, r0_12 -# 1166| r0_16(glval) = VariableAddress[#return] : -# 1166| r0_17(glval) = VariableAddress[y] : -# 1166| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 1166| mu0_19(int) = Store : &:r0_16, r0_18 -# 1163| r0_20(glval) = VariableAddress[#return] : -# 1163| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 -# 1163| v0_22(void) = UnmodeledUse : mu* -# 1163| v0_23(void) = AliasedUse : ~mu0_2 -# 1163| v0_24(void) = ExitFunction : +# 1165| r0_9(int *) = CopyValue : r0_8 +# 1165| r0_10(void *) = Convert : r0_9 +# 1165| r0_11(glval) = VariableAddress[x] : +# 1165| r0_12(int *) = CopyValue : r0_11 +# 1165| r0_13(void *) = Convert : r0_12 +# 1165| r0_14(int) = Constant[4] : +# 1165| r0_15(void *) = Call : func:r0_7, 0:r0_10, 1:r0_13, 2:r0_14 +# 1165| v0_16(void) = ^SizedBufferReadSideEffect[1] : &:r0_13, r0_14, ~mu0_2 +# 1165| mu0_17(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_10, r0_14 +# 1166| r0_18(glval) = VariableAddress[#return] : +# 1166| r0_19(glval) = VariableAddress[y] : +# 1166| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 1166| mu0_21(int) = Store : &:r0_18, r0_20 +# 1163| r0_22(glval) = VariableAddress[#return] : +# 1163| v0_23(void) = ReturnValue : &:r0_22, ~mu0_2 +# 1163| v0_24(void) = UnmodeledUse : mu* +# 1163| v0_25(void) = AliasedUse : ~mu0_2 +# 1163| v0_26(void) = ExitFunction : perf-regression.cpp: # 6| void Big::Big() diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 98786207c45..1f6d8bb3d3e 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -215,8 +215,9 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| m1_6(char) = Store : &:r1_2, r1_0 -# 70| m1_7(unknown) = Chi : total:m3_0, partial:m1_6 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| m1_7(char) = Store : &:r1_6, r1_0 +# 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -227,7 +228,7 @@ ssa.cpp: # 68| v2_4(void) = ExitFunction : # 69| Block 3 -# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_7 +# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_8 # 69| m3_1(int) = Phi : from 0:m0_4, from 1:m3_7 # 69| m3_2(char *) = Phi : from 0:m0_6, from 1:m1_5 # 69| r3_3(glval) = VariableAddress[n] : @@ -330,18 +331,19 @@ ssa.cpp: # 96| m0_9(Point) = Store : &:r0_6, r0_8 # 97| r0_10(glval) = FunctionAddress[Escape] : # 97| r0_11(glval) = VariableAddress[a] : -# 97| r0_12(void *) = Convert : r0_11 -# 97| v0_13(void) = Call : func:r0_10, 0:r0_12 -# 97| m0_14(unknown) = ^CallSideEffect : ~m0_5 -# 97| m0_15(unknown) = Chi : total:m0_5, partial:m0_14 -# 97| v0_16(void) = ^BufferReadSideEffect[0] : &:r0_12, ~m0_15 -# 97| m0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_12 -# 97| m0_18(unknown) = Chi : total:m0_15, partial:m0_17 -# 98| v0_19(void) = NoOp : -# 95| v0_20(void) = ReturnVoid : -# 95| v0_21(void) = UnmodeledUse : mu* -# 95| v0_22(void) = AliasedUse : ~m0_15 -# 95| v0_23(void) = ExitFunction : +# 97| r0_12(Point *) = CopyValue : r0_11 +# 97| r0_13(void *) = Convert : r0_12 +# 97| v0_14(void) = Call : func:r0_10, 0:r0_13 +# 97| m0_15(unknown) = ^CallSideEffect : ~m0_5 +# 97| m0_16(unknown) = Chi : total:m0_5, partial:m0_15 +# 97| v0_17(void) = ^BufferReadSideEffect[0] : &:r0_13, ~m0_16 +# 97| m0_18(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_13 +# 97| m0_19(unknown) = Chi : total:m0_16, partial:m0_18 +# 98| v0_20(void) = NoOp : +# 95| v0_21(void) = ReturnVoid : +# 95| v0_22(void) = UnmodeledUse : mu* +# 95| v0_23(void) = AliasedUse : ~m0_16 +# 95| v0_24(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -386,18 +388,19 @@ ssa.cpp: # 107| m0_15(int) = Store : &:r0_11, r0_14 # 108| r0_16(glval) = FunctionAddress[Escape] : # 108| r0_17(glval) = VariableAddress[a] : -# 108| r0_18(void *) = Convert : r0_17 -# 108| v0_19(void) = Call : func:r0_16, 0:r0_18 -# 108| m0_20(unknown) = ^CallSideEffect : ~m0_5 -# 108| m0_21(unknown) = Chi : total:m0_5, partial:m0_20 -# 108| v0_22(void) = ^BufferReadSideEffect[0] : &:r0_18, ~m0_21 -# 108| m0_23(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_18 -# 108| m0_24(unknown) = Chi : total:m0_21, partial:m0_23 -# 109| v0_25(void) = NoOp : -# 105| v0_26(void) = ReturnVoid : -# 105| v0_27(void) = UnmodeledUse : mu* -# 105| v0_28(void) = AliasedUse : ~m0_21 -# 105| v0_29(void) = ExitFunction : +# 108| r0_18(Point *) = CopyValue : r0_17 +# 108| r0_19(void *) = Convert : r0_18 +# 108| v0_20(void) = Call : func:r0_16, 0:r0_19 +# 108| m0_21(unknown) = ^CallSideEffect : ~m0_5 +# 108| m0_22(unknown) = Chi : total:m0_5, partial:m0_21 +# 108| v0_23(void) = ^BufferReadSideEffect[0] : &:r0_19, ~m0_22 +# 108| m0_24(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_19 +# 108| m0_25(unknown) = Chi : total:m0_22, partial:m0_24 +# 109| v0_26(void) = NoOp : +# 105| v0_27(void) = ReturnVoid : +# 105| v0_28(void) = UnmodeledUse : mu* +# 105| v0_29(void) = AliasedUse : ~m0_22 +# 105| v0_30(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -458,18 +461,19 @@ ssa.cpp: # 118| m0_23(Point) = Store : &:r0_20, r0_22 # 119| r0_24(glval) = FunctionAddress[Escape] : # 119| r0_25(glval) = VariableAddress[a] : -# 119| r0_26(void *) = Convert : r0_25 -# 119| v0_27(void) = Call : func:r0_24, 0:r0_26 -# 119| m0_28(unknown) = ^CallSideEffect : ~m0_19 -# 119| m0_29(unknown) = Chi : total:m0_19, partial:m0_28 -# 119| v0_30(void) = ^BufferReadSideEffect[0] : &:r0_26, ~m0_29 -# 119| m0_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_26 -# 119| m0_32(unknown) = Chi : total:m0_29, partial:m0_31 -# 120| v0_33(void) = NoOp : -# 116| v0_34(void) = ReturnVoid : -# 116| v0_35(void) = UnmodeledUse : mu* -# 116| v0_36(void) = AliasedUse : ~m0_29 -# 116| v0_37(void) = ExitFunction : +# 119| r0_26(Point *) = CopyValue : r0_25 +# 119| r0_27(void *) = Convert : r0_26 +# 119| v0_28(void) = Call : func:r0_24, 0:r0_27 +# 119| m0_29(unknown) = ^CallSideEffect : ~m0_19 +# 119| m0_30(unknown) = Chi : total:m0_19, partial:m0_29 +# 119| v0_31(void) = ^BufferReadSideEffect[0] : &:r0_27, ~m0_30 +# 119| m0_32(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_27 +# 119| m0_33(unknown) = Chi : total:m0_30, partial:m0_32 +# 120| v0_34(void) = NoOp : +# 116| v0_35(void) = ReturnVoid : +# 116| v0_36(void) = UnmodeledUse : mu* +# 116| v0_37(void) = AliasedUse : ~m0_30 +# 116| v0_38(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -773,21 +777,23 @@ ssa.cpp: # 184| m0_10(unsigned int &) = InitializeParameter[d] : &:r0_9 # 189| r0_11(glval) = VariableAddress[a] : # 189| r0_12(unsigned int &) = Load : &:r0_11, m0_4 -# 189| r0_13(glval) = VariableAddress[b] : -# 189| r0_14(unsigned int &) = Load : &:r0_13, m0_6 -# 190| r0_15(glval) = VariableAddress[c] : -# 190| r0_16(unsigned int &) = Load : &:r0_15, m0_8 -# 190| r0_17(unsigned int) = Load : &:r0_16, ~m0_1 -# 190| r0_18(glval) = VariableAddress[d] : -# 190| r0_19(unsigned int &) = Load : &:r0_18, m0_10 -# 190| r0_20(unsigned int) = Load : &:r0_19, ~m0_1 -# 186| m0_21(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_14, 2:r0_17, 3:r0_20 -# 186| m0_22(unknown) = Chi : total:m0_1, partial:m0_21 -# 192| v0_23(void) = NoOp : -# 184| v0_24(void) = ReturnVoid : -# 184| v0_25(void) = UnmodeledUse : mu* -# 184| v0_26(void) = AliasedUse : ~m0_22 -# 184| v0_27(void) = ExitFunction : +# 189| r0_13(glval) = CopyValue : r0_12 +# 189| r0_14(glval) = VariableAddress[b] : +# 189| r0_15(unsigned int &) = Load : &:r0_14, m0_6 +# 189| r0_16(glval) = CopyValue : r0_15 +# 190| r0_17(glval) = VariableAddress[c] : +# 190| r0_18(unsigned int &) = Load : &:r0_17, m0_8 +# 190| r0_19(unsigned int) = Load : &:r0_18, ~m0_1 +# 190| r0_20(glval) = VariableAddress[d] : +# 190| r0_21(unsigned int &) = Load : &:r0_20, m0_10 +# 190| r0_22(unsigned int) = Load : &:r0_21, ~m0_1 +# 186| m0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_13, 1:r0_16, 2:r0_19, 3:r0_22 +# 186| m0_24(unknown) = Chi : total:m0_1, partial:m0_23 +# 192| v0_25(void) = NoOp : +# 184| v0_26(void) = ReturnVoid : +# 184| v0_27(void) = UnmodeledUse : mu* +# 184| v0_28(void) = AliasedUse : ~m0_24 +# 184| v0_29(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 @@ -852,20 +858,122 @@ ssa.cpp: # 208| m0_8(unknown) = Chi : total:m0_5, partial:m0_7 # 209| r0_9(glval) = FunctionAddress[memcpy] : # 209| r0_10(glval) = VariableAddress[y] : -# 209| r0_11(void *) = Convert : r0_10 -# 209| r0_12(glval) = VariableAddress[x] : -# 209| r0_13(void *) = Convert : r0_12 -# 209| r0_14(int) = Constant[4] : -# 209| r0_15(void *) = Call : func:r0_9, 0:r0_11, 1:r0_13, 2:r0_14 -# 209| v0_16(void) = ^SizedBufferReadSideEffect[1] : &:r0_13, r0_14, ~mu0_2 -# 209| m0_17(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_11, r0_14 -# 209| m0_18(unknown) = Chi : total:m0_8, partial:m0_17 -# 210| r0_19(glval) = VariableAddress[#return] : -# 210| r0_20(glval) = VariableAddress[y] : -# 210| r0_21(int) = Load : &:r0_20, ~m0_18 -# 210| m0_22(int) = Store : &:r0_19, r0_21 -# 207| r0_23(glval) = VariableAddress[#return] : -# 207| v0_24(void) = ReturnValue : &:r0_23, m0_22 -# 207| v0_25(void) = UnmodeledUse : mu* -# 207| v0_26(void) = AliasedUse : ~m0_1 -# 207| v0_27(void) = ExitFunction : +# 209| r0_11(int *) = CopyValue : r0_10 +# 209| r0_12(void *) = Convert : r0_11 +# 209| r0_13(glval) = VariableAddress[x] : +# 209| r0_14(int *) = CopyValue : r0_13 +# 209| r0_15(void *) = Convert : r0_14 +# 209| r0_16(int) = Constant[4] : +# 209| r0_17(void *) = Call : func:r0_9, 0:r0_12, 1:r0_15, 2:r0_16 +# 209| v0_18(void) = ^SizedBufferReadSideEffect[1] : &:r0_15, r0_16, ~mu0_2 +# 209| m0_19(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_12, r0_16 +# 209| m0_20(unknown) = Chi : total:m0_8, partial:m0_19 +# 210| r0_21(glval) = VariableAddress[#return] : +# 210| r0_22(glval) = VariableAddress[y] : +# 210| r0_23(int) = Load : &:r0_22, ~m0_20 +# 210| m0_24(int) = Store : &:r0_21, r0_23 +# 207| r0_25(glval) = VariableAddress[#return] : +# 207| v0_26(void) = ReturnValue : &:r0_25, m0_24 +# 207| v0_27(void) = UnmodeledUse : mu* +# 207| v0_28(void) = AliasedUse : ~m0_1 +# 207| v0_29(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| m0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| m0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = 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) = 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) = VariableAddress[a_nopad] : +# 215| r0_15(glval) = 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) = VariableAddress[a_infer] : +# 216| r0_19(glval) = 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) = VariableAddress[b] : +# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 218| r0_24(glval) = VariableAddress[c] : +# 218| m0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 218| r0_26(int) = Constant[0] : +# 218| r0_27(glval) = 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) = VariableAddress[d] : +# 219| m0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 219| r0_32(int) = Constant[0] : +# 219| r0_33(glval) = 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) = 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) = VariableAddress[e] : +# 220| m0_43(char[2]) = Uninitialized[e] : &:r0_42 +# 220| r0_44(int) = Constant[0] : +# 220| r0_45(glval) = 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) = 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) = VariableAddress[f] : +# 221| m0_55(char[3]) = Uninitialized[f] : &:r0_54 +# 221| r0_56(int) = Constant[0] : +# 221| r0_57(glval) = 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) = 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 : + +# 226| char StringLiteralAliasing() +# 226| Block 0 +# 226| v0_0(void) = EnterFunction : +# 226| m0_1(unknown) = AliasedDefinition : +# 226| mu0_2(unknown) = UnmodeledDefinition : +# 227| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 227| v0_4(void) = Call : func:r0_3 +# 227| m0_5(unknown) = ^CallSideEffect : ~m0_1 +# 227| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 +# 229| r0_7(glval) = VariableAddress[s] : +# 229| r0_8(glval) = StringConstant["Literal"] : +# 229| r0_9(char *) = Convert : r0_8 +# 229| m0_10(char *) = Store : &:r0_7, r0_9 +# 230| r0_11(glval) = VariableAddress[#return] : +# 230| r0_12(glval) = VariableAddress[s] : +# 230| r0_13(char *) = Load : &:r0_12, m0_10 +# 230| r0_14(int) = Constant[2] : +# 230| r0_15(glval) = PointerAdd[1] : r0_13, r0_14 +# 230| r0_16(char) = Load : &:r0_15, ~m0_1 +# 230| m0_17(char) = Store : &:r0_11, r0_16 +# 226| r0_18(glval) = VariableAddress[#return] : +# 226| v0_19(void) = ReturnValue : &:r0_18, m0_17 +# 226| v0_20(void) = UnmodeledUse : mu* +# 226| v0_21(void) = AliasedUse : ~m0_6 +# 226| v0_22(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cd..6ae109dff44 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,22 @@ int ModeledCallTarget(int x) { return y; } +void InitArray() { + char a_pad[32] = ""; + char a_nopad[4] = "foo"; + char a_infer[] = "blah"; + char b[2]; + char c[2] = {}; + char d[2] = { 0 }; + char e[2] = { 0, 1 }; + char f[3] = { 0 }; +} + +extern void ExternalFunc(); + +char StringLiteralAliasing() { + ExternalFunc(); + + const char* s = "Literal"; + return s[2]; // Should be defined by `AliasedDefinition`, not `Chi` or `CallSideEffect`. +} diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 5ac06cadb55..9182300892d 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -218,7 +218,8 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| mu1_6(char) = Store : &:r1_2, r1_0 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| mu1_7(char) = Store : &:r1_6, r1_0 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -330,16 +331,17 @@ ssa.cpp: # 96| m0_8(Point) = Store : &:r0_5, r0_7 # 97| r0_9(glval) = FunctionAddress[Escape] : # 97| r0_10(glval) = VariableAddress[a] : -# 97| r0_11(void *) = Convert : r0_10 -# 97| v0_12(void) = Call : func:r0_9, 0:r0_11 -# 97| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 97| v0_14(void) = ^BufferReadSideEffect[0] : &:r0_11, ~mu0_2 -# 97| mu0_15(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -# 98| v0_16(void) = NoOp : -# 95| v0_17(void) = ReturnVoid : -# 95| v0_18(void) = UnmodeledUse : mu* -# 95| v0_19(void) = AliasedUse : ~mu0_2 -# 95| v0_20(void) = ExitFunction : +# 97| r0_11(Point *) = CopyValue : r0_10 +# 97| r0_12(void *) = Convert : r0_11 +# 97| v0_13(void) = Call : func:r0_9, 0:r0_12 +# 97| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +# 97| v0_15(void) = ^BufferReadSideEffect[0] : &:r0_12, ~mu0_2 +# 97| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_12 +# 98| v0_17(void) = NoOp : +# 95| v0_18(void) = ReturnVoid : +# 95| v0_19(void) = UnmodeledUse : mu* +# 95| v0_20(void) = AliasedUse : ~mu0_2 +# 95| v0_21(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -383,16 +385,17 @@ ssa.cpp: # 107| m0_14(int) = Store : &:r0_10, r0_13 # 108| r0_15(glval) = FunctionAddress[Escape] : # 108| r0_16(glval) = VariableAddress[a] : -# 108| r0_17(void *) = Convert : r0_16 -# 108| v0_18(void) = Call : func:r0_15, 0:r0_17 -# 108| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 108| v0_20(void) = ^BufferReadSideEffect[0] : &:r0_17, ~mu0_2 -# 108| mu0_21(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_17 -# 109| v0_22(void) = NoOp : -# 105| v0_23(void) = ReturnVoid : -# 105| v0_24(void) = UnmodeledUse : mu* -# 105| v0_25(void) = AliasedUse : ~mu0_2 -# 105| v0_26(void) = ExitFunction : +# 108| r0_17(Point *) = CopyValue : r0_16 +# 108| r0_18(void *) = Convert : r0_17 +# 108| v0_19(void) = Call : func:r0_15, 0:r0_18 +# 108| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 108| v0_21(void) = ^BufferReadSideEffect[0] : &:r0_18, ~mu0_2 +# 108| mu0_22(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_18 +# 109| v0_23(void) = NoOp : +# 105| v0_24(void) = ReturnVoid : +# 105| v0_25(void) = UnmodeledUse : mu* +# 105| v0_26(void) = AliasedUse : ~mu0_2 +# 105| v0_27(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -448,16 +451,17 @@ ssa.cpp: # 118| m0_20(Point) = Store : &:r0_17, r0_19 # 119| r0_21(glval) = FunctionAddress[Escape] : # 119| r0_22(glval) = VariableAddress[a] : -# 119| r0_23(void *) = Convert : r0_22 -# 119| v0_24(void) = Call : func:r0_21, 0:r0_23 -# 119| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 119| v0_26(void) = ^BufferReadSideEffect[0] : &:r0_23, ~mu0_2 -# 119| mu0_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -# 120| v0_28(void) = NoOp : -# 116| v0_29(void) = ReturnVoid : -# 116| v0_30(void) = UnmodeledUse : mu* -# 116| v0_31(void) = AliasedUse : ~mu0_2 -# 116| v0_32(void) = ExitFunction : +# 119| r0_23(Point *) = CopyValue : r0_22 +# 119| r0_24(void *) = Convert : r0_23 +# 119| v0_25(void) = Call : func:r0_21, 0:r0_24 +# 119| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 119| v0_27(void) = ^BufferReadSideEffect[0] : &:r0_24, ~mu0_2 +# 119| mu0_28(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_24 +# 120| v0_29(void) = NoOp : +# 116| v0_30(void) = ReturnVoid : +# 116| v0_31(void) = UnmodeledUse : mu* +# 116| v0_32(void) = AliasedUse : ~mu0_2 +# 116| v0_33(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -741,20 +745,22 @@ ssa.cpp: # 184| m0_10(unsigned int &) = InitializeParameter[d] : &:r0_9 # 189| r0_11(glval) = VariableAddress[a] : # 189| r0_12(unsigned int &) = Load : &:r0_11, m0_4 -# 189| r0_13(glval) = VariableAddress[b] : -# 189| r0_14(unsigned int &) = Load : &:r0_13, m0_6 -# 190| r0_15(glval) = VariableAddress[c] : -# 190| r0_16(unsigned int &) = Load : &:r0_15, m0_8 -# 190| r0_17(unsigned int) = Load : &:r0_16, ~mu0_2 -# 190| r0_18(glval) = VariableAddress[d] : -# 190| r0_19(unsigned int &) = Load : &:r0_18, m0_10 -# 190| r0_20(unsigned int) = Load : &:r0_19, ~mu0_2 -# 186| mu0_21(unknown) = InlineAsm : ~mu0_2, 0:r0_12, 1:r0_14, 2:r0_17, 3:r0_20 -# 192| v0_22(void) = NoOp : -# 184| v0_23(void) = ReturnVoid : -# 184| v0_24(void) = UnmodeledUse : mu* -# 184| v0_25(void) = AliasedUse : ~mu0_2 -# 184| v0_26(void) = ExitFunction : +# 189| r0_13(glval) = CopyValue : r0_12 +# 189| r0_14(glval) = VariableAddress[b] : +# 189| r0_15(unsigned int &) = Load : &:r0_14, m0_6 +# 189| r0_16(glval) = CopyValue : r0_15 +# 190| r0_17(glval) = VariableAddress[c] : +# 190| r0_18(unsigned int &) = Load : &:r0_17, m0_8 +# 190| r0_19(unsigned int) = Load : &:r0_18, ~mu0_2 +# 190| r0_20(glval) = VariableAddress[d] : +# 190| r0_21(unsigned int &) = Load : &:r0_20, m0_10 +# 190| r0_22(unsigned int) = Load : &:r0_21, ~mu0_2 +# 186| mu0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_13, 1:r0_16, 2:r0_19, 3:r0_22 +# 192| v0_24(void) = NoOp : +# 184| v0_25(void) = ReturnVoid : +# 184| v0_26(void) = UnmodeledUse : mu* +# 184| v0_27(void) = AliasedUse : ~mu0_2 +# 184| v0_28(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 @@ -817,19 +823,112 @@ ssa.cpp: # 208| mu0_6(int) = Uninitialized[y] : &:r0_5 # 209| r0_7(glval) = FunctionAddress[memcpy] : # 209| r0_8(glval) = VariableAddress[y] : -# 209| r0_9(void *) = Convert : r0_8 -# 209| r0_10(glval) = VariableAddress[x] : -# 209| r0_11(void *) = Convert : r0_10 -# 209| r0_12(int) = Constant[4] : -# 209| r0_13(void *) = Call : func:r0_7, 0:r0_9, 1:r0_11, 2:r0_12 -# 209| v0_14(void) = ^SizedBufferReadSideEffect[1] : &:r0_11, r0_12, ~mu0_2 -# 209| mu0_15(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_9, r0_12 -# 210| r0_16(glval) = VariableAddress[#return] : -# 210| r0_17(glval) = VariableAddress[y] : -# 210| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 210| m0_19(int) = Store : &:r0_16, r0_18 -# 207| r0_20(glval) = VariableAddress[#return] : -# 207| v0_21(void) = ReturnValue : &:r0_20, m0_19 -# 207| v0_22(void) = UnmodeledUse : mu* -# 207| v0_23(void) = AliasedUse : ~mu0_2 -# 207| v0_24(void) = ExitFunction : +# 209| r0_9(int *) = CopyValue : r0_8 +# 209| r0_10(void *) = Convert : r0_9 +# 209| r0_11(glval) = VariableAddress[x] : +# 209| r0_12(int *) = CopyValue : r0_11 +# 209| r0_13(void *) = Convert : r0_12 +# 209| r0_14(int) = Constant[4] : +# 209| r0_15(void *) = Call : func:r0_7, 0:r0_10, 1:r0_13, 2:r0_14 +# 209| v0_16(void) = ^SizedBufferReadSideEffect[1] : &:r0_13, r0_14, ~mu0_2 +# 209| mu0_17(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r0_10, r0_14 +# 210| r0_18(glval) = VariableAddress[#return] : +# 210| r0_19(glval) = VariableAddress[y] : +# 210| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 210| m0_21(int) = Store : &:r0_18, r0_20 +# 207| r0_22(glval) = VariableAddress[#return] : +# 207| v0_23(void) = ReturnValue : &:r0_22, m0_21 +# 207| v0_24(void) = UnmodeledUse : mu* +# 207| v0_25(void) = AliasedUse : ~mu0_2 +# 207| v0_26(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| mu0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = 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) = PointerAdd[1] : r0_3, r0_9 +# 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 215| r0_12(glval) = VariableAddress[a_nopad] : +# 215| r0_13(glval) = 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) = VariableAddress[a_infer] : +# 216| r0_17(glval) = 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) = VariableAddress[b] : +# 217| m0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 218| r0_22(glval) = VariableAddress[c] : +# 218| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 218| r0_24(int) = Constant[0] : +# 218| r0_25(glval) = 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) = VariableAddress[d] : +# 219| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 219| r0_30(int) = Constant[0] : +# 219| r0_31(glval) = 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) = 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) = VariableAddress[e] : +# 220| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 220| r0_40(int) = Constant[0] : +# 220| r0_41(glval) = 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) = 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) = VariableAddress[f] : +# 221| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 221| r0_50(int) = Constant[0] : +# 221| r0_51(glval) = 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) = 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 : + +# 226| char StringLiteralAliasing() +# 226| Block 0 +# 226| v0_0(void) = EnterFunction : +# 226| mu0_1(unknown) = AliasedDefinition : +# 226| mu0_2(unknown) = UnmodeledDefinition : +# 227| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 227| v0_4(void) = Call : func:r0_3 +# 227| mu0_5(unknown) = ^CallSideEffect : ~mu0_2 +# 229| r0_6(glval) = VariableAddress[s] : +# 229| r0_7(glval) = StringConstant["Literal"] : +# 229| r0_8(char *) = Convert : r0_7 +# 229| m0_9(char *) = Store : &:r0_6, r0_8 +# 230| r0_10(glval) = VariableAddress[#return] : +# 230| r0_11(glval) = VariableAddress[s] : +# 230| r0_12(char *) = Load : &:r0_11, m0_9 +# 230| r0_13(int) = Constant[2] : +# 230| r0_14(glval) = PointerAdd[1] : r0_12, r0_13 +# 230| r0_15(char) = Load : &:r0_14, ~mu0_2 +# 230| m0_16(char) = Store : &:r0_10, r0_15 +# 226| r0_17(glval) = VariableAddress[#return] : +# 226| v0_18(void) = ReturnValue : &:r0_17, m0_16 +# 226| v0_19(void) = UnmodeledUse : mu* +# 226| v0_20(void) = AliasedUse : ~mu0_2 +# 226| v0_21(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected index 9d77efe772f..f5ef2d77c98 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected @@ -13,7 +13,7 @@ | copy_from_prototype.cpp:13:7:13:7 | c | c::c(const c &) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(c &&) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(const c &) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | Unknown literal | +| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | | copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected index 7af2f7c8c17..e5539a762ab 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected @@ -1,3 +1,7 @@ +| file://:0:0:0:0 | __i | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:48:25:55 | __second | segfault.cpp:15:7:15:11 | tuple | diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected index cdc15c4b45a..0c8f9c1cff1 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected @@ -649,12 +649,14 @@ | test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Load: ++ ... | positive | | test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive | +| test.c:397:9:397:14 | CopyValue: ... , ... | positive strictlyPositive | | test.c:397:14:397:14 | Load: y | positive strictlyPositive | | test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive | | test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive | +| test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Store: ... += ... | positive strictlyPositive | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected deleted file mode 100644 index 00cdd21f9ed..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected +++ /dev/null @@ -1,53 +0,0 @@ -| staticlocals__staticlocals_f2_extractor | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_extractor | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_extractor | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_extractor | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_extractor | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_extractor | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_extractor | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_extractor | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_extractor | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_extractor | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_extractor | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_extractor | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_extractor | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_extractor | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_extractor | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_extractor | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_extractor | true | 22500 | 22499 | | -| staticlocals__staticlocals_f2_ql | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_ql | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_ql | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_ql | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_ql | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_ql | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_ql | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_ql | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_ql | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_ql | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_ql | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_ql | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22484 | | -| staticlocals__staticlocals_f2_ql | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_ql | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_ql | true | 22482 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22484 | 22482 | | -| staticlocals__staticlocals_f2_ql | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_ql | true | 22500 | 22499 | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql deleted file mode 100644 index 5b80f3c92a0..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql +++ /dev/null @@ -1,10 +0,0 @@ -// query-type: graph -import Compare - -from - Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, - string label -where - AllCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label) and - differentScope(scopeElement) -select scopeString, isEdge, x, y, label diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index e9dc12e62bf..68298b46256 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -1,8 +1,8 @@ missingOperand -| condition_decls.cpp:16:6:16:20 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:3:36:3 | Switch: switch (...) ... | Instruction 'Switch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:9:41:23 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:39:48:53 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | +| condition_decls.cpp:16:6:16:20 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | +| condition_decls.cpp:26:10:26:24 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | +| condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | +| condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected deleted file mode 100644 index 0e06bb202c4..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected +++ /dev/null @@ -1,3 +0,0 @@ -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql deleted file mode 100644 index f4b2509c17b..00000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql +++ /dev/null @@ -1,13 +0,0 @@ -import Compare - -string describeTemplate(ControlFlowNode node) { - node.isFromTemplateInstantiation(_) and - result = "instantiation" - or - node.isFromUninstantiatedTemplate(_) and - result = "uninstantiated" -} - -from ControlFlowNode n1, ControlFlowNode n2, string msg -where differentEdge(n1, n2, msg) -select getScopeName(n1), n1, n2, msg, concat(describeTemplate(n1), ", ") diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp new file mode 100644 index 00000000000..9a624d5d9f0 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp @@ -0,0 +1,19 @@ + + +class A { +public: + void foo(); + int k; +}; + +class B { +public: + template + B(T x) { + int k = x.k; + x.foo(); + } +}; + +A a; +B b(a); diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected new file mode 100644 index 00000000000..29d00dc147a --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected @@ -0,0 +1,2 @@ +| test.cpp:13:15:13:15 | k | +| test.cpp:14:7:14:9 | foo | diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql new file mode 100644 index 00000000000..233c7cdce8d --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Literal l +select l diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index 0f20692d443..f38eef610e4 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | __va_list_tag | | -| test.cpp:3:8:3:9 | s1<> | | -| test.cpp:3:8:3:9 | s1<> | | +| test.cpp:3:8:3:9 | s1<> | {...} | +| test.cpp:3:8:3:9 | s1<> | (null) | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:7:8:7:9 | s3> | (unnamed) | diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.expected b/cpp/ql/test/library-tests/templates/CPP-204/element.expected index 6cb84a117d5..44384471af9 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.expected +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.expected @@ -1,6 +1,12 @@ | file://:0:0:0:0 | | | file://:0:0:0:0 | 0 | | file://:0:0:0:0 | (global namespace) | +| file://:0:0:0:0 | B | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | Y | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | __va_list_tag & | | file://:0:0:0:0 | __va_list_tag && | diff --git a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected index 802903a40b6..99a6201c59c 100644 --- a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected +++ b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected @@ -317,8 +317,8 @@ | test.cpp:19:9:19:24 | call to expression | | test.cpp:19:9:19:25 | ExprStmt | | test.cpp:19:9:19:25 | ExprStmt | -| test.cpp:19:15:19:18 | Unknown literal | | test.cpp:19:15:19:18 | call to funx | +| test.cpp:19:15:19:18 | funx | | test.cpp:19:20:19:23 | (reference to) | | test.cpp:19:20:19:23 | valx | | test.cpp:19:20:19:23 | valx | @@ -356,8 +356,8 @@ | test.cpp:30:13:30:22 | call to expression | | test.cpp:30:13:30:23 | ExprStmt | | test.cpp:30:13:30:23 | ExprStmt | -| test.cpp:30:15:30:20 | Unknown literal | | test.cpp:30:15:30:20 | call to eparse | +| test.cpp:30:15:30:20 | eparse | | test.cpp:31:9:31:9 | return ... | | test.cpp:31:9:31:9 | return ... | | test.cpp:34:6:34:11 | define | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp new file mode 100644 index 00000000000..4f16f623daf --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp @@ -0,0 +1,4 @@ +template +class Int { }; + +Int<10> i; diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected new file mode 100644 index 00000000000..ffa9bfb2cf4 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected @@ -0,0 +1,2 @@ +| test.cpp:2:7:2:9 | Int<10> | file://:0:0:0:0 | int | test.cpp:4:5:4:6 | 10 | +| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | i | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql new file mode 100644 index 00000000000..900424eb501 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Class c +select c, c.getATemplateArgumentKind(), c.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp new file mode 100644 index 00000000000..625258906db --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp @@ -0,0 +1,5 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +int addToSelf() { return i + i; }; + +int bar() { return addToSelf<10>(); } diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected new file mode 100644 index 00000000000..493e9f03b20 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected @@ -0,0 +1,2 @@ +| test.cpp:3:5:3:5 | addToSelf | file://:0:0:0:0 | int | test.cpp:5:30:5:31 | 10 | +| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | i | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql new file mode 100644 index 00000000000..98f8a4112d4 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Function f +select f, f.getATemplateArgumentKind(), f.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp new file mode 100644 index 00000000000..1baabe3ca30 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp @@ -0,0 +1,19 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +struct C { }; + +static const int one1 = 1, one2 = 1; +C c = C(); +C e; + +template +struct D { }; + +D a; +D b; + +template +struct E { }; + +E z; + diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected new file mode 100644 index 00000000000..fa5df86f68f --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected @@ -0,0 +1,13 @@ +| test.cpp:3:8:3:8 | C<1> | 0 | int | test.cpp:5:25:5:25 | 1 | +| test.cpp:3:8:3:8 | C<2> | 0 | int | file://:0:0:0:0 | 2 | +| test.cpp:3:8:3:8 | C | 0 | int | file://:0:0:0:0 | x | +| test.cpp:10:8:10:8 | D | 0 | | test.cpp:9:19:9:19 | T | +| test.cpp:10:8:10:8 | D | 1 | T | file://:0:0:0:0 | X | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | int | +| test.cpp:10:8:10:8 | D | 1 | int | test.cpp:12:8:12:8 | 2 | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | long | +| test.cpp:10:8:10:8 | D | 1 | long | file://:0:0:0:0 | 2 | +| test.cpp:16:8:16:8 | E | 0 | | test.cpp:15:19:15:19 | T | +| test.cpp:16:8:16:8 | E | 1 | T * | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | 0 | | file://:0:0:0:0 | int | +| test.cpp:16:8:16:8 | E | 1 | int * | file://:0:0:0:0 | 0 | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql new file mode 100644 index 00000000000..68d597e0f98 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql @@ -0,0 +1,14 @@ +import cpp + +string maybeGetTemplateArgumentKind(Declaration d, int i) { + ( + if exists(d.getTemplateArgumentKind(i)) + then result = d.getTemplateArgumentKind(i).toString() + else result = "" + ) and + i = [0 .. d.getNumberOfTemplateArguments()] +} + +from Declaration d, int i +where i >= 0 and i < d.getNumberOfTemplateArguments() +select d, i, maybeGetTemplateArgumentKind(d, i), d.getTemplateArgument(i) diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index cd58ff3912a..4180c41eb5f 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -300,45 +300,47 @@ test.cpp: # 44| valnum = r0_7 # 44| r0_27(int *) = Load : &:r0_26, m0_8 # 44| valnum = m0_8 -# 44| m0_28(int) = Store : &:r0_27, r0_25 +# 44| r0_28(glval) = CopyValue : r0_27 +# 44| valnum = m0_8 +# 44| m0_29(int) = Store : &:r0_28, r0_25 # 44| valnum = r0_25 -# 44| m0_29(unknown) = Chi : total:m0_1, partial:m0_28 +# 44| m0_30(unknown) = Chi : total:m0_1, partial:m0_29 # 44| valnum = unique -# 45| r0_30(glval) = VariableAddress[p0] : +# 45| r0_31(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_31(int) = Load : &:r0_30, m0_4 +# 45| r0_32(int) = Load : &:r0_31, m0_4 # 45| valnum = m0_4 -# 45| r0_32(glval) = VariableAddress[p1] : +# 45| r0_33(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_33(int) = Load : &:r0_32, m0_6 +# 45| r0_34(int) = Load : &:r0_33, m0_6 # 45| valnum = m0_6 -# 45| r0_34(int) = Add : r0_31, r0_33 +# 45| r0_35(int) = Add : r0_32, r0_34 # 45| valnum = r0_19 -# 45| r0_35(glval) = VariableAddress[global03] : +# 45| r0_36(glval) = VariableAddress[global03] : # 45| valnum = r0_20 -# 45| r0_36(int) = Load : &:r0_35, ~m0_29 +# 45| r0_37(int) = Load : &:r0_36, ~m0_30 # 45| valnum = unique -# 45| r0_37(int) = Add : r0_34, r0_36 -# 45| valnum = r0_37 -# 45| r0_38(glval) = VariableAddress[x] : +# 45| r0_38(int) = Add : r0_35, r0_37 +# 45| valnum = r0_38 +# 45| r0_39(glval) = VariableAddress[x] : # 45| valnum = r0_9 -# 45| m0_39(int) = Store : &:r0_38, r0_37 -# 45| valnum = r0_37 -# 46| r0_40(glval) = VariableAddress[x] : +# 45| m0_40(int) = Store : &:r0_39, r0_38 +# 45| valnum = r0_38 +# 46| r0_41(glval) = VariableAddress[x] : # 46| valnum = r0_9 -# 46| r0_41(int) = Load : &:r0_40, m0_39 -# 46| valnum = r0_37 -# 46| r0_42(glval) = VariableAddress[y] : +# 46| r0_42(int) = Load : &:r0_41, m0_40 +# 46| valnum = r0_38 +# 46| r0_43(glval) = VariableAddress[y] : # 46| valnum = r0_11 -# 46| m0_43(int) = Store : &:r0_42, r0_41 -# 46| valnum = r0_37 -# 47| v0_44(void) = NoOp : -# 39| r0_45(glval) = VariableAddress[#return] : +# 46| m0_44(int) = Store : &:r0_43, r0_42 +# 46| valnum = r0_38 +# 47| v0_45(void) = NoOp : +# 39| r0_46(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_46(void) = ReturnValue : &:r0_45 -# 39| v0_47(void) = UnmodeledUse : mu* -# 39| v0_48(void) = AliasedUse : ~m0_29 -# 39| v0_49(void) = ExitFunction : +# 39| v0_47(void) = ReturnValue : &:r0_46 +# 39| v0_48(void) = UnmodeledUse : mu* +# 39| v0_49(void) = AliasedUse : ~m0_30 +# 39| v0_50(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -677,84 +679,86 @@ test.cpp: # 92| valnum = r0_3 # 92| m0_6(int) = Store : &:r0_5, r0_4 # 92| valnum = r0_4 -# 92| m0_7(int) = Store : &:r0_3, r0_4 +# 92| r0_7(int) = CopyValue : r0_4 # 92| valnum = r0_4 -# 93| r0_8(glval) = VariableAddress[#return] : -# 93| valnum = r0_8 -# 93| r0_9(glval) = VariableAddress[x] : +# 92| m0_8(int) = Store : &:r0_3, r0_7 +# 92| valnum = r0_4 +# 93| r0_9(glval) = VariableAddress[#return] : +# 93| valnum = r0_9 +# 93| r0_10(glval) = VariableAddress[x] : # 93| valnum = r0_3 -# 93| r0_10(int) = Load : &:r0_9, m0_7 +# 93| r0_11(int) = Load : &:r0_10, m0_8 # 93| valnum = r0_4 -# 93| m0_11(int) = Store : &:r0_8, r0_10 +# 93| m0_12(int) = Store : &:r0_9, r0_11 # 93| valnum = r0_4 -# 91| r0_12(glval) = VariableAddress[#return] : -# 91| valnum = r0_8 -# 91| v0_13(void) = ReturnValue : &:r0_12, m0_11 -# 91| v0_14(void) = UnmodeledUse : mu* -# 91| v0_15(void) = AliasedUse : ~m0_1 -# 91| v0_16(void) = ExitFunction : +# 91| r0_13(glval) = VariableAddress[#return] : +# 91| valnum = r0_9 +# 91| v0_14(void) = ReturnValue : &:r0_13, m0_12 +# 91| v0_15(void) = UnmodeledUse : mu* +# 91| v0_16(void) = AliasedUse : ~m0_1 +# 91| v0_17(void) = ExitFunction : # 104| int inheritanceConversions(Derived*) # 104| Block 0 -# 104| v0_0(void) = EnterFunction : -# 104| m0_1(unknown) = AliasedDefinition : +# 104| v0_0(void) = EnterFunction : +# 104| m0_1(unknown) = AliasedDefinition : # 104| valnum = unique -# 104| mu0_2(unknown) = UnmodeledDefinition : +# 104| mu0_2(unknown) = UnmodeledDefinition : # 104| valnum = unique -# 104| r0_3(glval) = VariableAddress[pd] : +# 104| r0_3(glval) = VariableAddress[pd] : # 104| valnum = r0_3 -# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3 +# 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3 # 104| valnum = m0_4 -# 105| r0_5(glval) = VariableAddress[x] : +# 105| r0_5(glval) = VariableAddress[x] : # 105| valnum = unique -# 105| r0_6(glval) = VariableAddress[pd] : +# 105| r0_6(glval) = VariableAddress[pd] : # 105| valnum = r0_3 -# 105| r0_7(Derived *) = Load : &:r0_6, m0_4 +# 105| r0_7(Derived *) = Load : &:r0_6, m0_4 # 105| valnum = m0_4 -# 105| r0_8(Base *) = ConvertToBase[Derived : Base] : r0_7 +# 105| r0_8(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_7 # 105| valnum = r0_8 -# 105| r0_9(glval) = FieldAddress[b] : r0_8 +# 105| r0_9(glval) = FieldAddress[b] : r0_8 # 105| valnum = r0_9 -# 105| r0_10(int) = Load : &:r0_9, ~m0_1 +# 105| r0_10(int) = Load : &:r0_9, ~m0_1 # 105| valnum = r0_10 -# 105| m0_11(int) = Store : &:r0_5, r0_10 +# 105| m0_11(int) = Store : &:r0_5, r0_10 # 105| valnum = r0_10 -# 106| r0_12(glval) = VariableAddress[pb] : +# 106| r0_12(glval) = VariableAddress[pb] : # 106| valnum = r0_12 -# 106| r0_13(glval) = VariableAddress[pd] : +# 106| r0_13(glval) = VariableAddress[pd] : # 106| valnum = r0_3 -# 106| r0_14(Derived *) = Load : &:r0_13, m0_4 +# 106| r0_14(Derived *) = Load : &:r0_13, m0_4 # 106| valnum = m0_4 -# 106| r0_15(Base *) = ConvertToBase[Derived : Base] : r0_14 +# 106| r0_15(Base *) = ConvertToNonVirtualBase[Derived : Base] : r0_14 # 106| valnum = r0_8 -# 106| m0_16(Base *) = Store : &:r0_12, r0_15 +# 106| m0_16(Base *) = Store : &:r0_12, r0_15 # 106| valnum = r0_8 -# 107| r0_17(glval) = VariableAddress[y] : +# 107| r0_17(glval) = VariableAddress[y] : # 107| valnum = r0_17 -# 107| r0_18(glval) = VariableAddress[pb] : +# 107| r0_18(glval) = VariableAddress[pb] : # 107| valnum = r0_12 -# 107| r0_19(Base *) = Load : &:r0_18, m0_16 +# 107| r0_19(Base *) = Load : &:r0_18, m0_16 # 107| valnum = r0_8 -# 107| r0_20(glval) = FieldAddress[b] : r0_19 +# 107| r0_20(glval) = FieldAddress[b] : r0_19 # 107| valnum = r0_9 -# 107| r0_21(int) = Load : &:r0_20, ~m0_1 +# 107| r0_21(int) = Load : &:r0_20, ~m0_1 # 107| valnum = r0_21 -# 107| m0_22(int) = Store : &:r0_17, r0_21 +# 107| m0_22(int) = Store : &:r0_17, r0_21 # 107| valnum = r0_21 -# 109| r0_23(glval) = VariableAddress[#return] : +# 109| r0_23(glval) = VariableAddress[#return] : # 109| valnum = r0_23 -# 109| r0_24(glval) = VariableAddress[y] : +# 109| r0_24(glval) = VariableAddress[y] : # 109| valnum = r0_17 -# 109| r0_25(int) = Load : &:r0_24, m0_22 +# 109| r0_25(int) = Load : &:r0_24, m0_22 # 109| valnum = r0_21 -# 109| m0_26(int) = Store : &:r0_23, r0_25 +# 109| m0_26(int) = Store : &:r0_23, r0_25 # 109| valnum = r0_21 -# 104| r0_27(glval) = VariableAddress[#return] : +# 104| r0_27(glval) = VariableAddress[#return] : # 104| valnum = r0_23 -# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26 -# 104| v0_29(void) = UnmodeledUse : mu* -# 104| v0_30(void) = AliasedUse : ~m0_1 -# 104| v0_31(void) = ExitFunction : +# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26 +# 104| v0_29(void) = UnmodeledUse : mu* +# 104| v0_30(void) = AliasedUse : ~m0_1 +# 104| v0_31(void) = ExitFunction : # 112| void test06() # 112| Block 0 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected index 9cb1aaa02af..920a1f820f8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected @@ -1 +1,3 @@ +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Bad overflow check. | +| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Bad overflow check. | | test.cpp:3:11:3:19 | ... < ... | Bad overflow check. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected index 2318c286c60..8d1911edfcd 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/PointlessSelfComparison.expected @@ -1,3 +1,4 @@ +| templates.cpp:17:5:17:25 | ... < ... | Self comparison. | | test.cpp:13:11:13:21 | ... == ... | Self comparison. | | test.cpp:79:11:79:32 | ... == ... | Self comparison. | | test.cpp:83:10:83:15 | ... == ... | Self comparison. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp new file mode 100644 index 00000000000..e359fb098eb --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -0,0 +1,130 @@ +// Signed-comparison tests + +/* 1. Signed-signed comparison. The semantics are undefined. */ +bool cannotHoldAnother8(int n1) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + 8 < n1; // BAD +} + +/* 2. Signed comparison with a narrower unsigned type. The narrower + type gets promoted to the (signed) larger type, and so the + semantics are undefined. */ +bool cannotHoldAnotherUShort(int n1, unsigned short delta) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // BAD +} + +/* 3. Signed comparison with a non-narrower unsigned type. The + signed type gets promoted to (a possibly wider) unsigned type, + and the resulting comparison is unsigned. */ +bool cannotHoldAnotherUInt(int n1, unsigned int delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // GOOD +} + +bool shortShort1(unsigned short n1, unsigned short delta) { + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return n1 + delta < n1; +} + +bool shortShort2(unsigned short n1, unsigned short delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return (unsigned short)(n1 + delta) < n1; // GOOD +} + +/* Distinguish `varname` from `ptr->varname` and `obj.varname` */ +struct N { + int n1; +} n, *np; + +bool shortStruct1(unsigned short n1, unsigned short delta) { + return np->n1 + delta < n1; // GOOD +} + +bool shortStruct1a(unsigned short n1, unsigned short delta) { + return n1 + delta < n.n1; // GOOD +} + +bool shortStruct2(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n.n1; // GOOD +} + +struct se { + int xPos; + short yPos; + short xSize; + short ySize; +}; + +extern se *getSo(void); + +bool func1(se *so) { + se *o = getSo(); + if (so->xPos + so->xSize < so->xPos // BAD + || so->xPos > o->xPos + o->xSize) { // GOOD + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return false; + } + return true; +} + +bool checkOverflow3(unsigned int a, unsigned short b) { + return (a + b < a); // GOOD +} + +struct C { + unsigned int length; +}; + +int checkOverflow4(unsigned int ioff, C c) { + // not deleted by gcc or clang + if ((int)(ioff + c.length) < (int)ioff) return 0; // GOOD + return 1; +} + +int overflow12(int n) { + // not deleted by gcc or clang + return (n + 32 <= (unsigned)n? -1: 1); // BAD: n + 32 can overflow +} + +bool multipleCasts(char x) { + + // BAD [UNDETECTED - BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow +} + +bool multipleCasts2(char x) { + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; +} + +int does_it_overflow(int n1, unsigned short delta) { + return n1 + (unsigned)delta < n1; // GOOD: everything converted to unsigned +} + +int overflow12b(int n) { + // not deleted by gcc or clang + return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow +} + +#define MACRO(E1, E2) (E1) <= (E2)? -1: 1 + +int overflow12_macro(int n) { + return MACRO((unsigned)(n + 32), (unsigned)n); // GOOD: inside a macro expansion +} + diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected new file mode 100644 index 00000000000..414bc74f99e --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -0,0 +1,5 @@ +| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:73:6:73:36 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref new file mode 100644 index 00000000000..dde64840202 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref @@ -0,0 +1 @@ +Likely Bugs/Arithmetic/SignedOverflowCheck.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp new file mode 100644 index 00000000000..0fbd2643404 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/templates.cpp @@ -0,0 +1,22 @@ +struct C1 { + static const int value = 5; +}; + +struct C2 { + static const int value = 6; +}; + +template +bool compareValues() { + // Not all instantiations have T1 and T2 equal. Even if that's the case for + // all instantiations in the program, there could still be more such + // instantiations outside. + return + T1::value < T2::value || // GOOD + T1::value < T1::value || // BAD [NOT DETECTED] + C1::value < C1::value ; // BAD +} + +bool callCompareValues() { + return compareValues || compareValues(); +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 4669b709bc4..e36956f9c69 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -1,11 +1,11 @@ // Test for BadAdditionOverflowCheck. bool checkOverflow1(unsigned short a, unsigned short b) { - return (a + b < a); // BAD: a + b is automatically promoted to int. + return (a + b < a); // BAD: comparison always false (due to promotion). } // Test for BadAdditionOverflowCheck. bool checkOverflow2(unsigned short a, unsigned short b) { - return ((unsigned short)(a + b) < a); // GOOD: explicit cast + return ((unsigned short)(a + b) < a); // GOOD } // Test for PointlessSelfComparison. diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/a.c b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/a.c new file mode 100644 index 00000000000..5b31d31b9fb --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/a.c @@ -0,0 +1,19 @@ + +__attribute__((format(printf, 1, 3))) +void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...) +{ + // ... +} + +__attribute__((format(printf, 1, 3))) +void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...); + +char *getString(); + +void test_custom_printf1() +{ + myMultiplyDefinedPrintf("string", getString()); // GOOD + myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED] + myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) + myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/b.c b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/b.c new file mode 100644 index 00000000000..b0addf37881 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/b.c @@ -0,0 +1,16 @@ + +__attribute__((format(printf, 2, 3))) +void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition + +__attribute__((format(printf, 2, 3))) +void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...); + +char *getString(); + +void test_custom_printf2(char *string) +{ + myMultiplyDefinedPrintf("string", getString()); // GOOD + myMultiplyDefinedPrintf(getString(), "string"); // BAD [NOT DETECTED] + myMultiplyDefinedPrintf2("string", getString()); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) + myMultiplyDefinedPrintf2(getString(), "string"); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected index 65f4f546976..c67057710bb 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/WrongTypeFormatArguments.expected @@ -16,6 +16,43 @@ | printf1.h:114:18:114:18 | d | This argument should be of type 'long double' but is of type 'double' | | printf1.h:147:19:147:19 | i | This argument should be of type 'long long' but is of type 'int' | | printf1.h:148:19:148:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int' | +| printf1.h:160:18:160:18 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:161:21:161:21 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:167:17:167:17 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:168:18:168:18 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:169:19:169:19 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:174:17:174:17 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:175:18:175:18 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:176:19:176:19 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:180:17:180:17 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:181:20:181:20 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:183:18:183:18 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:184:21:184:21 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:186:19:186:19 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:187:22:187:22 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:189:19:189:19 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:190:22:190:22 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:192:19:192:19 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:193:22:193:22 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:194:25:194:25 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:198:24:198:24 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:199:21:199:21 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:202:26:202:26 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:203:23:203:23 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:206:25:206:25 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:207:22:207:22 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:210:26:210:26 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:211:23:211:23 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:214:28:214:28 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:215:28:215:28 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:216:25:216:25 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:221:18:221:18 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:222:20:222:20 | s | This argument should be of type 'int' but is of type 'char *' | +| printf1.h:225:23:225:23 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:228:24:228:24 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:231:25:231:25 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:234:25:234:25 | i | This argument should be of type 'char *' but is of type 'int' | +| printf1.h:235:22:235:22 | s | This argument should be of type 'int' but is of type 'char *' | | real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' | | real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' | | real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/a.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/a.c new file mode 100644 index 00000000000..17d1bd98fed --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/a.c @@ -0,0 +1,16 @@ + +__attribute__((format(printf, 1, 3))) +void myMultiplyDefinedPrintf(const char *format, const char *extraArg, ...) +{ + // ... +} +__attribute__((format(printf, 1, 3))) +void myMultiplyDefinedPrintf2(const char *format, const char *extraArg, ...); + +void test_custom_printf1() +{ + myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD + myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED] + myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) + myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/b.c b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/b.c new file mode 100644 index 00000000000..adf443c1e9d --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/b.c @@ -0,0 +1,14 @@ + +__attribute__((format(printf, 2, 3))) +void myMultiplyDefinedPrintf(const char *extraArg, const char *format, ...); // this declaration does not match the definition + +__attribute__((format(printf, 2, 3))) +void myMultiplyDefinedPrintf2(const char *extraArg, const char *format, ...); + +void test_custom_printf2() +{ + myMultiplyDefinedPrintf("%i", "%f", 1); // GOOD + myMultiplyDefinedPrintf("%i", "%f", 1.0f); // BAD [NOT DETECTED] + myMultiplyDefinedPrintf2("%i", "%f", 1); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) + myMultiplyDefinedPrintf2("%i", "%f", 1.0f); // GOOD (we can't tell which declaration is correct so we have to assume this is OK) +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h index ab9a9e18635..4517cfadf56 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/printf1.h @@ -151,3 +151,86 @@ void fun4() printf("%qi\n", ll); // GOOD printf("%qu\n", ull); // GOOD } + +void complexFormatSymbols(int i, const char *s) +{ + // positional arguments + printf("%1$i", i, s); // GOOD + printf("%2$s", i, s); // GOOD + printf("%1$s", i, s); // BAD + printf("%2$i", i, s); // BAD + + // width / precision + printf("%4i", i); // GOOD + printf("%.4i", i); // GOOD + printf("%4.4i", i); // GOOD + printf("%4s", i); // BAD + printf("%.4s", i); // BAD + printf("%4.4s", i); // BAD + + printf("%4s", s); // GOOD + printf("%.4s", s); // GOOD + printf("%4.4s", s); // GOOD + printf("%4i", s); // BAD + printf("%.4i", s); // BAD + printf("%4.4i", s); // BAD + + // variable width / precision + printf("%*s", i, s); // GOOD + printf("%*s", s, s); // BAD + printf("%*s", i, i); // BAD + printf("%.*s", i, s); // GOOD + printf("%.*s", s, s); // BAD + printf("%.*s", i, i); // BAD + printf("%*.4s", i, s); // GOOD + printf("%*.4s", s, s); // BAD + printf("%*.4s", i, i); // BAD + printf("%4.*s", i, s); // GOOD + printf("%4.*s", s, s); // BAD + printf("%4.*s", i, i); // BAD + printf("%*.*s", i, i, s); // GOOD + printf("%*.*s", s, i, s); // BAD + printf("%*.*s", i, s, s); // BAD + printf("%*.*s", i, i, i); // BAD + + // positional arguments mixed with variable width / precision + printf("%2$*1$s", i, s); // GOOD + printf("%2$*2$s", i, s); // BAD + printf("%1$*1$s", i, s); // BAD + + printf("%2$*1$.4s", i, s); // GOOD + printf("%2$*2$.4s", i, s); // BAD + printf("%1$*1$.4s", i, s); // BAD + + printf("%2$.*1$s", i, s); // GOOD + printf("%2$.*2$s", i, s); // BAD + printf("%1$.*1$s", i, s); // BAD + + printf("%2$4.*1$s", i, s); // GOOD + printf("%2$4.*2$s", i, s); // BAD + printf("%1$4.*1$s", i, s); // BAD + + printf("%2$*1$.*1$s", i, s); // GOOD + printf("%2$*2$.*1$s", i, s); // BAD + printf("%2$*1$.*2$s", i, s); // BAD + printf("%1$*1$.*1$s", i, s); // BAD + + // left justify flag + printf("%-4s", s); // GOOD + printf("%1$-4s", s); // GOOD + printf("%-4i", s); // BAD + printf("%1$-4i", s); // BAD + + printf("%1$-4s", s, i); // GOOD + printf("%2$-4s", s, i); // BAD + + printf("%1$-.4s", s, i); // GOOD + printf("%2$-.4s", s, i); // BAD + + printf("%1$-4.4s", s, i); // GOOD + printf("%2$-4.4s", s, i); // BAD + + printf("%1$-*2$s", s, i); // GOOD + printf("%2$-*2$s", s, i); // BAD + printf("%1$-*1$s", s, i); // BAD +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected new file mode 100644 index 00000000000..6c2fa97858c --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected @@ -0,0 +1,8 @@ +| test.cpp:12:25:12:29 | call to ntohl | Unchecked use of data from network function $@ | test.cpp:12:25:12:29 | call to ntohl | call to ntohl | +| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@ | test.cpp:85:10:85:14 | call to ntohl | call to ntohl | +| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@ | test.cpp:99:8:99:12 | call to ntohl | call to ntohl | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref new file mode 100644 index 00000000000..2647a5479f2 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref @@ -0,0 +1 @@ +Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp new file mode 100644 index 00000000000..e3f01f9ae77 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp @@ -0,0 +1,100 @@ + +typedef unsigned int size_t; +void *memcpy(void *s1, const void *s2, size_t n); +size_t strlen(const char *s); +int ntohl(int x); + +void test1(const char *source, size_t len) +{ + char buffer[256]; + size_t len2 = ntohl(len); + + memcpy(buffer, source, ntohl(len)); // BAD + + if (len2 < 256) + { + memcpy(buffer, source, len2); // GOOD + } + + if (source != 0) + { + memcpy(buffer, source, len2); // BAD + } + + if ((len2 < 256) && (source != 0)) + { + memcpy(buffer, source, len2); // GOOD + } + + if ((len2 < 256) || (source != 0)) + { + memcpy(buffer, source, len2); // BAD + } + + if (len2 < 256) + { + if (source != 0) + { + memcpy(buffer, source, len2); // GOOD + } + } + + if (len2 >= 256) + { + // fail + } else { + memcpy(buffer, source, len2); // GOOD + } + + if (len2 + 1 < 256) + { + memcpy(buffer, source, len2 + 1); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, strlen(source)); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, len2); // BAD + } + + buffer[len2] = 0; // BAD + + if (len2 < 256) + { + buffer[len2] = 0; // GOOD + } + + { + unsigned short lens = len2; + buffer[lens] = 0; // BAD + } + + if (len2 < 256) + { + unsigned short lens = len2; + buffer[lens] = 0; // GOOD + } + + size_t len3 = 0; + if (len3 < 256) + { + len3 = ntohl(len); + buffer[len3] = 0; // BAD + } +} + +void test2(size_t len) +{ + char buffer[256]; + + buffer[len] = 0; // BAD +} + +void test3(size_t len) +{ + test2(ntohl(len)); +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected index 8a3acb1aeb5..c6883e156d1 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected @@ -1,3 +1,14 @@ +| test2.cpp:15:32:15:33 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:15:32:15:33 | call to context | boost::asio::ssl::context::context | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:45:35:45:98 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:35:45:98 | call to context | boost::asio::ssl::context::context | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | 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_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 | | 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 | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp new file mode 100644 index 00000000000..5679cee8b0f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp @@ -0,0 +1,55 @@ +#include "asio/boost_simulation.hpp" + +void good1() +{ + // GOOD + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad1() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void good2() +{ + // GOOD [FALSE POSITIVE x 3] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void bad2() +{ + // BAD: missing disable SSLv3 [WITH FALSE POSITIVE x 2] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void good3() +{ + // GOOD + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad3() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void bad4() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); +} + + diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected new file mode 100644 index 00000000000..60964c8f178 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected @@ -0,0 +1,3 @@ +| examples.cpp:38:3:38:18 | call to initDeviceConfig | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | examples.cpp:13:5:13:20 | initDeviceConfig | initDeviceConfig | examples.cpp:37:16:37:21 | config | config | +| test.cpp:22:2:22:17 | call to maybeInitialize1 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:4:5:4:20 | maybeInitialize1 | maybeInitialize1 | test.cpp:19:6:19:6 | a | a | +| test.cpp:68:2:68:17 | call to maybeInitialize2 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:51:6:51:21 | maybeInitialize2 | maybeInitialize2 | test.cpp:66:6:66:6 | a | a | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref new file mode 100644 index 00000000000..5150d627257 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp new file mode 100644 index 00000000000..ccb15904d02 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp @@ -0,0 +1,43 @@ +// based on the qhelp + +int getMaxDevices(); +bool fetchIsDeviceEnabled(int deviceNumber); +int fetchDeviceChannel(int deviceNumber); +void notifyChannel(int channel); + +struct DeviceConfig { + bool isEnabled; + int channel; +}; + +int initDeviceConfig(DeviceConfig *ref, int deviceNumber) { + if (deviceNumber >= getMaxDevices()) { + // No device with that number, return -1 to indicate failure + return -1; + } + // Device with that number, fetch parameters and initialize struct + ref->isEnabled = fetchIsDeviceEnabled(deviceNumber); + ref->channel = fetchDeviceChannel(deviceNumber); + // Return 0 to indicate success + return 0; +} + +void notifyGood(int deviceNumber) { + DeviceConfig config; + int statusCode = initDeviceConfig(&config, deviceNumber); + if (statusCode == 0) { + // GOOD: Status code returned by initialization function is checked, so this is safe + if (config.isEnabled) { + notifyChannel(config.channel); + } + } +} + +int notifyBad(int deviceNumber) { + DeviceConfig config; + initDeviceConfig(&config, deviceNumber); + // BAD: Using config without checking the status code that is returned + if (config.isEnabled) { + notifyChannel(config.channel); + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp new file mode 100644 index 00000000000..a3c9b0a24aa --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp @@ -0,0 +1,96 @@ + +void use(int i); + +int maybeInitialize1(int *v) +{ + static int resources = 100; + + if (resources == 0) + { + return 0; // FAIL + } + + *v = resources--; + return 1; // SUCCESS +} + +void test1() +{ + int a, b, c, d, e, f; + int result1, result2; + + maybeInitialize1(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize1(&b) == 1) // GOOD + { + use(b); + } + + if (maybeInitialize1(&c) == 0) // BAD (initialization check is wrong) [NOT DETECTED] + { + use(c); + } + + result1 = maybeInitialize1(&d); // BAD (initialization stored but not checked) [NOT DETECTED] + use(d); + + result2 = maybeInitialize1(&e); // GOOD + if (result2 == 1) + { + use(e); + } + + if (maybeInitialize1(&f) == 0) // GOOD + { + return; + } + use(f); +} + +bool maybeInitialize2(int *v) +{ + static int resources = 100; + + if (resources > 0) + { + *v = resources--; + return true; // SUCCESS + } + + return false; // FAIL +} + +void test2() +{ + int a, b; + + maybeInitialize2(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize2(&b)) // GOOD + { + use(b); + } +} + +int alwaysInitialize(int *v) +{ + static int resources = 0; + + *v = resources++; + return 1; // SUCCESS +} + +void test3() +{ + int a, b; + + alwaysInitialize(&a); // GOOD (initialization never fails) + use(a); + + if (alwaysInitialize(&b) == 1) // GOOD + { + use(b); + } +} diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme new file mode 100644 index 00000000000..98a075d5495 --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme @@ -0,0 +1,1918 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..bd182f697bf --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme @@ -0,0 +1,1933 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties new file mode 100644 index 00000000000..495bdeebdac --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties @@ -0,0 +1,2 @@ +description: Add support for value template parameters. +compatibility: partial diff --git a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp index 9a71290694d..409be1030e7 100644 --- a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp +++ b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp @@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp index 118e91ed4d9..04f01720ce6 100644 --- a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp @@ -33,7 +33,7 @@ the query cannot be changed by a malicious user.

    -
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • +
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • OWASP: Preventing LDAP Injection in Java.
  • AntiXSS doc: LdapFilterEncode.
  • AntiXSS doc: LdapDistinguishedNameEncode.
  • diff --git a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp index 4e70b06531a..3aff9901bfc 100644 --- a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp @@ -36,10 +36,10 @@ which ensures the content is appropriately escaped.

  • - XML Injection (The Web Application Security Consortium). + Web Application Security Consortium: XML Injection.
  • - WriteRaw (Microsoft documentation). + Microsoft Docs: WriteRaw.
  • diff --git a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp index 5f95181c092..e1dbe9c1bd0 100644 --- a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp @@ -14,7 +14,7 @@ was not intended to be loaded, and executing arbitrary code.

    Avoid loading assemblies based on user provided input. If this is not possible, ensure that the path is validated before being used with Assembly. For example, compare the provided input -against a whitelist of known safe assemblies, or confirm that path is restricted to a single +against a whitelist of known safe assemblies, or confirm that the path is restricted to a single directory which only contains safe assemblies.

    @@ -30,8 +30,8 @@ is only loaded if the user input matches one of those options.

    -
  • - System.Reflection.Assembly (Microsoft documentation). +
  • Microsoft: + System.Reflection.Assembly.
  • diff --git a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql index c09a67d756c..cce122ffa62 100644 --- a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql +++ b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql @@ -1,6 +1,6 @@ /** - * @name Do not use hard-coded encryption keys. - * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hardcoded value. + * @name Hard-coded encryption key + * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hard-coded value. * @kind problem * @id cs/hardcoded-key * @problem.severity error diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp index ae69402eb7e..c59feeed61c 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp @@ -3,7 +3,6 @@ "qhelp.dtd"> -

    Finds uses of insecure SQL Connections string by not enabling the Encrypt option.

    SQL Server connections where the client is not enforcing the encryption in transit are susceptible to multiple attacks, including a man-in-the-middle, that would potentially compromise the user credentials and/or the TDS session. @@ -29,18 +28,17 @@ - -

  • - Selectively using secure connection to SQL Server +
  • Microsoft, SQL Protocols blog: + Selectively using secure connection to SQL Server.
  • -
  • - Net SqlClient (ADO .Net) +
  • Microsoft: + SqlConnection.ConnectionString Property. +
  • +
  • Microsoft: + Using Connection String Keywords with SQL Server Native Client. +
  • +
  • Microsoft: + Setting the connection properties.
  • -
  • SQL native driver (SNAC) -
  • -
  • - JDBC driver -
  • -
    diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index 0f855150aa9..78bcc1c19e5 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -1,6 +1,6 @@ /** * @name Insecure SQL connection - * @description TODO. + * @description Using an SQL Server connection without enforcing encryption is a security vulnerability. * @kind path-problem * @id cs/insecure-sql-connection * @problem.severity error diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp index 7df415aff5b..6d5d298c8e4 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp @@ -51,7 +51,7 @@ This next example shows how to specify the X-Frame-Options header w
  • OWASP: -Clickjacking Defense Cheat Sheet. +Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp index 7acfd20fe3a..3c68b74a1d9 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index edd0e15c247..40022d40573 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -5,16 +5,13 @@ * @kind problem * @id cs/unsafe-deserialization * @problem.severity warning + * @precision low * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision low - */ - import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization from Call deserializeCall, Sink sink where deserializeCall.getAnArgument() = sink.asExpr() diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp index ef946f40136..3ba934ba391 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index b0b659857ab..80a3762a8bc 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -5,16 +5,13 @@ * @kind path-problem * @id cs/unsafe-deserialization-untrusted-input * @problem.severity error + * @precision high * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision high - */ - import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph from TaintTrackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp index 989796b6738..3cf3cdaba6e 100644 --- a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp +++ b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp @@ -32,7 +32,7 @@ It also shows how to remedy the problem by validating the user input against a k
  • OWASP: -XSS +XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp index 2e8e4fcf272..11b1136db4d 100644 --- a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp +++ b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp @@ -38,7 +38,7 @@ The solution is to set the DtdProcessing property to DtdProce
  • OWASP: -XML External Entity (XXE) Prevention Cheat Sheet. +XML External Entity (XXE) Prevention Cheat Sheet.
  • Microsoft Docs: System.XML: Security considerations. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 0abfa14023d..73cdbd20989 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or @@ -42,6 +43,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +109,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +120,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +147,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +162,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +176,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +193,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +208,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +239,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index eb07be7f30c..0e4f800bb1b 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -34,7 +34,7 @@ private newtype TOpcode = TPointerSub() or TPointerDiff() or TConvert() or - TConvertToBase() or + TConvertToNonVirtualBase() or TConvertToVirtualBase() or TConvertToDerived() or TCheckedConvertOrNull() or @@ -110,6 +110,8 @@ abstract class RelationalOpcode extends CompareOpcode { } abstract class CopyOpcode extends Opcode { } +abstract class ConvertToBaseOpcode extends UnaryOpcode { } + abstract class MemoryAccessOpcode extends Opcode { } abstract class ReturnOpcode extends Opcode { } @@ -302,11 +304,11 @@ module Opcode { final override string toString() { result = "Convert" } } - class ConvertToBase extends UnaryOpcode, TConvertToBase { - final override string toString() { result = "ConvertToBase" } + class ConvertToNonVirtualBase extends ConvertToBaseOpcode, TConvertToNonVirtualBase { + final override string toString() { result = "ConvertToNonVirtualBase" } } - class ConvertToVirtualBase extends UnaryOpcode, TConvertToVirtualBase { + class ConvertToVirtualBase extends ConvertToBaseOpcode, TConvertToVirtualBase { final override string toString() { result = "ConvertToVirtualBase" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd..01c135abf13 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 049983c9126..6cc1127c4bd 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { @@ -983,14 +981,22 @@ class InheritanceConversionInstruction extends UnaryInstruction { * to the address of a direct non-virtual base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll index 0d2627e183f..72881a7c720 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll @@ -52,6 +52,15 @@ private module Cached { ) } + cached + predicate hasStringLiteral( + Callable callable, Language::AST ast, CSharpType type, StringLiteral literal + ) { + literal = ast and + literal.getEnclosingCallable() = callable and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -232,8 +241,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -265,12 +280,6 @@ private module Cached { .getInstructionConstantValue(getInstructionTag(instruction)) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached CSharpType getInstructionExceptionType(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29..e10e266b2ab 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126..6cc1127c4bd 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { @@ -983,14 +981,22 @@ class InheritanceConversionInstruction extends UnaryInstruction { * to the address of a direct non-virtual base class. */ class ConvertToBaseInstruction extends InheritanceConversionInstruction { - ConvertToBaseInstruction() { getOpcode() instanceof Opcode::ConvertToBase } + ConvertToBaseInstruction() { getOpcode() instanceof ConvertToBaseOpcode } +} + +/** + * Represents an instruction that converts from the address of a derived class + * to the address of a direct non-virtual base class. + */ +class ConvertToNonVirtualBaseInstruction extends ConvertToBaseInstruction { + ConvertToNonVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToNonVirtualBase } } /** * Represents an instruction that converts from the address of a derived class * to the address of a virtual base class. */ -class ConvertToVirtualBaseInstruction extends InheritanceConversionInstruction { +class ConvertToVirtualBaseInstruction extends ConvertToBaseInstruction { ConvertToVirtualBaseInstruction() { getOpcode() instanceof Opcode::ConvertToVirtualBase } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index 1f5064f6766..a90eec8c17c 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -105,7 +105,7 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset) { ( // REVIEW: See the REVIEW comment bellow // // Converting to a non-virtual base class adds the offset of the base class. - // exists(ConvertToBaseInstruction convert | + // exists(ConvertToNonVirtualBaseInstruction convert | // convert = instr and // bitOffset = Ints::mul(convert.getDerivation().getByteOffset(), 8) // ) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a..c8362098295 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll index ac400b210a5..36b1285f9e0 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll @@ -144,6 +144,7 @@ private IRType getIRTypeForPRValue(Type type) { string getOpaqueTagIdentityString(Type tag) { result = tag.getQualifiedName() } +cached private newtype TCSharpType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TGLValueAddressType(Type type) { any() } or @@ -163,6 +164,7 @@ class CSharpType extends TCSharpType { * Gets the `IRType` that represents this `CSharpType`. Many different `CSharpType`s can map to a * single `IRType`. */ + cached abstract IRType getIRType(); /** diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll similarity index 97% rename from csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 4e401eb4804..57b3a78485b 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,6 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs index 11f05a14a00..bd796aa9f51 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs deleted file mode 100644 index 48c74335f6f..00000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs +++ /dev/null @@ -1,34 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs index 11f05a14a00..bd796aa9f51 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs deleted file mode 100644 index 293c0cdf355..00000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs +++ /dev/null @@ -1,45 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace UI - { - namespace WebControls - { - public class TextBox - { - public string Text { get; set; } - } - } - } - - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index eb08326b794..13ebaf316d7 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -346,3 +346,25 @@ namespace System.Web.Helpers public static void Validate() { } } } + +namespace System.Web.Script.Serialization +{ + // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class JavaScriptSerializer + { + public JavaScriptSerializer() => throw null; + public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; + public object DeserializeObject(string input) => throw null; + } + + // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + abstract public class JavaScriptTypeResolver + { + } + + // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver + { + public SimpleTypeResolver() => throw null; + } +} diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index de3b189e1ee..7faadbefbe8 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -62,8 +62,8 @@
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp index cab60173a62..f1ba450d4a0 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp @@ -67,7 +67,7 @@ in the environment variable or user-supplied value are not given any special tre
  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp index 7415235610c..e469415d683 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp @@ -39,7 +39,7 @@ treatment.

  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp index 8b8b0eff847..2cfdca624fb 100644 --- a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp @@ -37,7 +37,7 @@ connection is a secure SSL connection.

    Class HttpsURLConnection.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp index 5856086330f..cec4937c8f7 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp @@ -38,7 +38,7 @@ Class HttpsURLConnection. Class SSLSocket.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp index 56e9be97345..bf0dbc0bcac 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp @@ -33,7 +33,7 @@ uses explicit SSL factories, which are preferable.

    Class SSLSocketFactory.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp index 4fb0ad88b45..61b50a986e3 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp @@ -58,7 +58,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql index 18cf624375f..bb4df03cd4f 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql @@ -12,7 +12,7 @@ import java import semmle.code.java.dataflow.FlowSources -import UnsafeDeserialization +import semmle.code.java.security.UnsafeDeserialization import DataFlow::PathGraph class UnsafeDeserializationConfig extends TaintTracking::Configuration { diff --git a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp index 75c5a2d4d7a..93d420f7495 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp +++ b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp @@ -52,7 +52,7 @@ OWASP vulnerability description:
  • OWASP guidance on parsing xml files: -XXE Prevention Cheat Sheet. +XXE Prevention Cheat Sheet.
  • Paper by Timothy Morgen: diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll similarity index 100% rename from java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll rename to java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll diff --git a/java/ql/src/semmle/code/java/security/XmlParsers.qll b/java/ql/src/semmle/code/java/security/XmlParsers.qll index 37a72f8128e..1f582489497 100644 --- a/java/ql/src/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/src/semmle/code/java/security/XmlParsers.qll @@ -49,7 +49,7 @@ abstract class ParserConfig extends MethodAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#DocumentBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j */ /** The class `javax.xml.parsers.DocumentBuilderFactory`. */ @@ -227,7 +227,7 @@ class SafeDocumentBuilder extends DocumentBuilderConstruction { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLInputFactory_.28a_StAX_parser.29 + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser */ /** The class `javax.xml.stream.XMLInputFactory`. */ @@ -353,7 +353,7 @@ class SafeXmlInputFactory extends VarAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxbuilder */ /** @@ -429,7 +429,7 @@ class SafeSAXBuilder extends VarAccess { /* * The case in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller * will be split into two, one covers a SAXParser as a sink, the other the SAXSource as a sink. */ @@ -545,7 +545,7 @@ class SafeSAXParser extends MethodAccess { } } -/* SAXReader: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXReader */ +/* SAXReader: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxreader */ /** * The class `org.dom4j.io.SAXReader`. */ @@ -621,7 +621,7 @@ class SafeSAXReader extends VarAccess { } } -/* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLReader */ +/* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader */ /** The class `org.xml.sax.XMLReader`. */ class XMLReader extends RefType { XMLReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") } @@ -756,7 +756,7 @@ class CreatedSafeXMLReader extends Call { /* * SAXSource in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.transform.sax.SAXSource` */ @@ -811,7 +811,7 @@ class SafeSAXSource extends Expr { } } -/* Transformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#TransformerFactory */ +/* Transformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory */ /** An access to a method use for configuring a transformer or schema. */ abstract class TransformerConfig extends MethodAccess { /** Holds if the configuration is disabled */ @@ -975,7 +975,7 @@ class SafeTransformer extends MethodAccess { } /* - * SAXTransformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXTransformerFactory + * SAXTransformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxtransformerfactory * Has an extra method called newFilter. */ @@ -996,7 +996,7 @@ class SAXTransformerFactoryNewXMLFilter extends XmlParserCall { } } -/* Schema: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SchemaFactory */ +/* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */ /** The class `javax.xml.validation.SchemaFactory`. */ class SchemaFactory extends RefType { SchemaFactory() { this.hasQualifiedName("javax.xml.validation", "SchemaFactory") } @@ -1060,7 +1060,7 @@ class SafeSchemaFactory extends VarAccess { } } -/* Unmarshaller: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller */ +/* Unmarshaller: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.bind.Unmarshaller`. */ class XmlUnmarshaller extends RefType { XmlUnmarshaller() { this.hasQualifiedName("javax.xml.bind", "Unmarshaller") } @@ -1081,7 +1081,7 @@ class XmlUnmarshal extends XmlParserCall { override predicate isSafe() { none() } } -/* XPathExpression: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XPathExpression */ +/* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */ /** The class `javax.xml.xpath.XPathExpression`. */ class XPathExpression extends RefType { XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") } diff --git a/javascript/config/suites/javascript/correctness-core b/javascript/config/suites/javascript/correctness-core index 6a53405e1c3..d6b91e83a07 100644 --- a/javascript/config/suites/javascript/correctness-core +++ b/javascript/config/suites/javascript/correctness-core @@ -37,5 +37,6 @@ + semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions ++ semmlecode-javascript-queries/Statements/IgnoreArrayResult.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/InconsistentLoopOrientation.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/UnreachableStatement.ql: /Correctness/Statements diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index d80ddeaf303..308713c0c1a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -1,5 +1,16 @@ package com.semmle.js.extractor; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.regex.Pattern; + import com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase; import com.semmle.js.extractor.trapcache.CachingTrapWriter; import com.semmle.js.extractor.trapcache.ITrapCache; @@ -10,15 +21,6 @@ import com.semmle.util.files.FileUtil; import com.semmle.util.io.WholeIO; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Pattern; /** * The file extractor extracts a single file and handles source archive population and TRAP caching; @@ -154,6 +156,9 @@ public class FileExtractor { byte[] bytes = new byte[fileHeaderSize]; int length = fis.read(bytes); + if (length == -1) + return false; + // Avoid invalid or unprintable UTF-8 files. if (config.getDefaultEncoding().equals("UTF-8") && hasUnprintableUtf8(bytes, length)) { return true; @@ -167,6 +172,9 @@ public class FileExtractor { return true; } + // Avoid Touchstone files + if (isTouchstone(bytes, length)) return true; + return false; } catch (IOException e) { Exceptions.ignore(e, "Let extractor handle this one."); @@ -198,6 +206,11 @@ public class FileExtractor { return false; } + private boolean isTouchstone(byte[] bytes, int length) { + String s = new String(bytes, 0, length, StandardCharsets.US_ASCII); + return s.startsWith("! TOUCHSTONE file ") || s.startsWith("[Version] 2.0"); + } + /** * Returns true if the byte sequence contains invalid UTF-8 or unprintable ASCII characters. */ diff --git a/javascript/extractor/tests/ts/input/touchstone-file.ts b/javascript/extractor/tests/ts/input/touchstone-file.ts new file mode 100644 index 00000000000..a72a1dc56af --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file.ts @@ -0,0 +1,2 @@ +! TOUCHSTONE file generated by me +[Version] 2.0 diff --git a/javascript/extractor/tests/ts/input/touchstone-file2.ts b/javascript/extractor/tests/ts/input/touchstone-file2.ts new file mode 100644 index 00000000000..d642e0260b1 --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file2.ts @@ -0,0 +1 @@ +[Version] 2.0 diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 14024ec8f38..917ab81a3e7 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -13,122 +13,10 @@ */ import javascript -import DOMProperties -import semmle.javascript.frameworks.xUnit -import semmle.javascript.RestrictedLocations import ExprHasNoEffect +import semmle.javascript.RestrictedLocations -/** - * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. - * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. - * - * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries - * no semantic information), and expression statements with an ordinary (non-JSDoc) comment - * attached to them. - */ -predicate isDeclaration(Expr e) { - (e instanceof VarAccess or e instanceof PropAccess) and - exists(e.getParent().(ExprStmt).getDocumentation().getATag()) -} - -/** - * Holds if there exists a getter for a property called `name` anywhere in the program. - */ -predicate isGetterProperty(string name) { - // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... - exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | - // ... where `descriptor` defines a getter - defProp.hasPropertyAttributeWrite("get", _) - or - // ... where `descriptor` may define a getter - exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | - descriptor.isIncomplete(_) - or - // minimal escape analysis for the descriptor - exists(DataFlow::InvokeNode invk | - not invk = defProp and - descriptor.flowsTo(invk.getAnArgument()) - ) - ) - ) - or - // there is an object expression with a getter property `name` - exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) -} - -/** - * A property access that may invoke a getter. - */ -class GetterPropertyAccess extends PropAccess { - override predicate isImpure() { isGetterProperty(getPropertyName()) } -} - -/** - * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where - * `dummy` is some expression whose value is discarded, and which simply - * exists to prevent the call from being interpreted as a direct eval. - */ -predicate isIndirectEval(CallExpr c, Expr dummy) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is - * some expression whose value is discarded, and which simply exists - * to prevent the call from being interpreted as a method call. - */ -predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1) = callee and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if evaluating `e` has no side effects (except potentially allocating - * and initializing a new object). - * - * For calls, we do not check whether their arguments have any side effects: - * even if they do, the call itself is useless and should be flagged by this - * query. - */ -predicate noSideEffects(Expr e) { - e.isPure() - or - // `new Error(...)`, `new SyntaxError(...)`, etc. - forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | - f.(ExternalType).getASupertype*().getName() = "Error" - ) -} from Expr e -where - noSideEffects(e) and - inVoidContext(e) and - // disregard pure expressions wrapped in a void(...) - not e instanceof VoidExpr and - // filter out directives (unknown directives are handled by UnknownDirective.ql) - not exists(Directive d | e = d.getExpr()) and - // or about externs - not e.inExternsFile() and - // don't complain about declarations - not isDeclaration(e) and - // exclude DOM properties, which sometimes have magical auto-update properties - not isDOMProperty(e.(PropAccess).getPropertyName()) and - // exclude xUnit.js annotations - not e instanceof XUnitAnnotation and - // exclude common patterns that are most likely intentional - not isIndirectEval(_, e) and - not isReceiverSuppressingCall(_, e, _) and - // exclude anonymous function expressions as statements; these can only arise - // from a syntax error we already flag - not exists(FunctionExpr fe, ExprStmt es | fe = e | - fe = es.getExpr() and - not exists(fe.getName()) - ) +where hasNoEffect(e) select e.(FirstLineOf), "This expression has no effect." diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 858f719ba0a..bee980e5fd8 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -3,6 +3,8 @@ */ import javascript +import DOMProperties +import semmle.javascript.frameworks.xUnit /** * Holds if `e` appears in a syntactic context where its value is discarded. @@ -37,3 +39,121 @@ predicate inVoidContext(Expr e) { or exists(LogicalBinaryExpr logical | e = logical.getRightOperand() and inVoidContext(logical)) } + + +/** + * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. + * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. + * + * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries + * no semantic information), and expression statements with an ordinary (non-JSDoc) comment + * attached to them. + */ +predicate isDeclaration(Expr e) { + (e instanceof VarAccess or e instanceof PropAccess) and + exists(e.getParent().(ExprStmt).getDocumentation().getATag()) +} + +/** + * Holds if there exists a getter for a property called `name` anywhere in the program. + */ +predicate isGetterProperty(string name) { + // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... + exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | + // ... where `descriptor` defines a getter + defProp.hasPropertyAttributeWrite("get", _) + or + // ... where `descriptor` may define a getter + exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | + descriptor.isIncomplete(_) + or + // minimal escape analysis for the descriptor + exists(DataFlow::InvokeNode invk | + not invk = defProp and + descriptor.flowsTo(invk.getAnArgument()) + ) + ) + ) + or + // there is an object expression with a getter property `name` + exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) +} + +/** + * A property access that may invoke a getter. + */ +class GetterPropertyAccess extends PropAccess { + override predicate isImpure() { isGetterProperty(getPropertyName()) } +} + +/** + * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where + * `dummy` is some expression whose value is discarded, and which simply + * exists to prevent the call from being interpreted as a direct eval. + */ +predicate isIndirectEval(CallExpr c, Expr dummy) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is + * some expression whose value is discarded, and which simply exists + * to prevent the call from being interpreted as a method call. + */ +predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1) = callee and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if evaluating `e` has no side effects (except potentially allocating + * and initializing a new object). + * + * For calls, we do not check whether their arguments have any side effects: + * even if they do, the call itself is useless and should be flagged by this + * query. + */ +predicate noSideEffects(Expr e) { + e.isPure() + or + // `new Error(...)`, `new SyntaxError(...)`, etc. + forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | + f.(ExternalType).getASupertype*().getName() = "Error" + ) +} + +/** + * Holds if the expression `e` should be reported as having no effect. + */ +predicate hasNoEffect(Expr e) { + noSideEffects(e) and + inVoidContext(e) and + // disregard pure expressions wrapped in a void(...) + not e instanceof VoidExpr and + // filter out directives (unknown directives are handled by UnknownDirective.ql) + not exists(Directive d | e = d.getExpr()) and + // or about externs + not e.inExternsFile() and + // don't complain about declarations + not isDeclaration(e) and + // exclude DOM properties, which sometimes have magical auto-update properties + not isDOMProperty(e.(PropAccess).getPropertyName()) and + // exclude xUnit.js annotations + not e instanceof XUnitAnnotation and + // exclude common patterns that are most likely intentional + not isIndirectEval(_, e) and + not isReceiverSuppressingCall(_, e, _) and + // exclude anonymous function expressions as statements; these can only arise + // from a syntax error we already flag + not exists(FunctionExpr fe, ExprStmt es | fe = e | + fe = es.getExpr() and + not exists(fe.getName()) + ) +} \ No newline at end of file diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index 771c446c66f..a5e0a78b8cc 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -68,6 +68,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index b23557aa557..90e6f2762e2 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -83,6 +83,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp index 807574c5898..015e510f0fb 100644 --- a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp +++ b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp @@ -71,6 +71,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp index 0502889fba0..dcbf0ba6f07 100644 --- a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -37,7 +37,7 @@ Sanitizing the user-controlled data prevents the vulnerability:
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp index 1c3fde01798..0e6ed6456c9 100644 --- a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp @@ -48,7 +48,7 @@
  • OWASP: - XSS + XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/Xss.qhelp b/javascript/ql/src/Security/CWE-079/Xss.qhelp index 34ea1d821b6..c974c87b188 100644 --- a/javascript/ql/src/Security/CWE-079/Xss.qhelp +++ b/javascript/ql/src/Security/CWE-079/Xss.qhelp @@ -33,12 +33,12 @@ leaving the website vulnerable to cross-site scripting.
  • OWASP: -DOM based +DOM based XSS Prevention Cheat Sheet.
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp index 02cce7c5911..6c36fde4b28 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp @@ -10,8 +10,8 @@ attacks such as cross-site scripting. One particular example of this is HTML ent where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as &lt; and the double-quote character as &quot;. -Other examples include backslash-escaping for including untrusted data in string literals and -percent-encoding for URI components. +Other examples include backslash escaping or JSON encoding for including untrusted data in string +literals, and percent-encoding for URI components.

    The reverse process of replacing escape sequences with the characters they represent is known as diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index a150a2d7a7a..6340a2fcedc 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -46,7 +46,12 @@ string getStringValue(RegExpLiteral rl) { */ 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,38 +59,31 @@ 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. + * A method call that performs string replacement. */ -class Replacement extends DataFlow::Node { - RegExpLiteral pattern; - - 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() - ) - } - +abstract class Replacement extends DataFlow::Node { /** * Holds if this replacement replaces the string `input` with `output`. */ - predicate replaces(string input, string output) { - exists(DataFlow::MethodCallNode mcn | - mcn = this and - input = getStringValue(pattern) and - output = mcn.getArgument(1).getStringValue() - ) - } + abstract predicate replaces(string input, string output); + + /** + * Gets the input of this replacement. + */ + abstract DataFlow::Node getInput(); + + /** + * Gets the output of this replacement. + */ + abstract DataFlow::SourceNode getOutput(); /** * Holds if this replacement escapes `char` using `metachar`. @@ -118,9 +116,12 @@ class Replacement extends DataFlow::Node { /** * Gets the previous replacement in this chain of replacements. */ - Replacement getPreviousReplacement() { - result = getASimplePredecessor*(this.(DataFlow::MethodCallNode).getReceiver()) - } + Replacement getPreviousReplacement() { result.getOutput() = getASimplePredecessor*(getInput()) } + + /** + * Gets the next replacement in this chain of replacements. + */ + Replacement getNextReplacement() { this = result.getPreviousReplacement() } /** * Gets an earlier replacement in this chain of replacements that @@ -130,7 +131,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,11 +145,100 @@ 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) + ) ) } } +/** + * A call to `String.prototype.replace` that replaces all instances of a pattern. + */ +class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { + RegExpLiteral pattern; + + GlobalStringReplacement() { + this.getMethodName() = "replace" and + pattern.flow().(DataFlow::SourceNode).flowsTo(this.getArgument(0)) and + this.getNumArgument() = 2 and + pattern.isGlobal() + } + + override predicate replaces(string input, string output) { + input = getStringValue(pattern) and + output = this.getArgument(1).getStringValue() + 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.asExpr().(ObjectExpr).getPropertyByName(input).getInit().getStringValue() = output + ) + } + + override DataFlow::Node getInput() { result = this.getReceiver() } + + override DataFlow::SourceNode getOutput() { result = this } +} + +/** + * A call to `JSON.stringify`, viewed as a string replacement. + */ +class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { + JsonStringifyReplacement() { this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") } + + override predicate replaces(string input, string output) { + input = "\\" and output = "\\\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { result = this.getArgument(0) } + + override DataFlow::SourceNode getOutput() { result = this } +} + +/** + * A call to `JSON.parse`, viewed as a string replacement. + */ +class JsonParseReplacement extends Replacement { + JsonParserCall self; + + JsonParseReplacement() { this = self } + + override predicate replaces(string input, string output) { + input = "\\\\" and output = "\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { result = self.getInput() } + + override DataFlow::SourceNode getOutput() { result = self.getOutput() } +} + +/** + * A string replacement wrapped in a utility function. + */ +class WrappedReplacement extends Replacement, DataFlow::CallNode { + int i; + + Replacement inner; + + WrappedReplacement() { + exists(DataFlow::FunctionNode wrapped | wrapped.getFunction() = getACallee() | + wrapped.getParameter(i).flowsTo(inner.getPreviousReplacement*().getInput()) and + inner.getNextReplacement*().getOutput().flowsTo(wrapped.getAReturn()) + ) + } + + override predicate replaces(string input, string output) { inner.replaces(input, output) } + + override DataFlow::Node getInput() { result = getArgument(i) } + + override DataFlow::SourceNode getOutput() { result = this } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 9b230852919..e0ccf71572f 100644 --- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -45,7 +45,7 @@

  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp index ad659015d67..e73ea063b5d 100644 --- a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp +++ b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp @@ -67,7 +67,7 @@
  • OWASP: - Clickjacking Defense Cheat Sheet. + Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index e7b956b10f4..5f5b77cbd7d 100644 --- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -41,7 +41,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Neal Poole: diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp index d4d36fe09bc..392df3e6cbd 100644 --- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp @@ -31,7 +31,7 @@ website of their choosing, which facilitates phishing attacks: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp index cb54477dde5..2052f16146b 100644 --- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp index 1832a803a77..8d4bc0ab5d0 100644 --- a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp +++ b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp @@ -36,7 +36,7 @@ can be used:
  • OWASP: -Denial of Service Cheat Sheet. +Denial of Service Cheat Sheet.
  • Wikipedia: Denial-of-service attack. diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp index 2b1d2b02a31..1efdbe694b1 100644 --- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp +++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp @@ -50,6 +50,6 @@ -
  • OWASP: Password storage.
  • +
  • OWASP: Password storage.
  • diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp new file mode 100644 index 00000000000..70e3cb4e5cc --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -0,0 +1,48 @@ + + + +

    +The concat, join and slice methods are +pure and do not modify any of the inputs or the array the method is called +on. It is therefore generally an error to ignore the return value from a call +to one of these methods. +

    + +
    + + +

    +Use the returned value from the calls to concat, join +or slice. +

    + +
    + + +

    +A function extend is defined in the following example. The +function uses the concat method to add elements to the +arr array. However, the extend function has no +effect as the return value from concat is ignored: +

    + + + +

    +Assigning the returned value from the call to concat to the +arr variable fixes the error: +

    + + + +
    + + +
  • Mozilla Developer Network: Array concat.
  • +
  • Mozilla Developer Network: Array slice.
  • +
  • Mozilla Developer Network: Array join.
  • + +
    +
    diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql new file mode 100644 index 00000000000..6f6698797f1 --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -0,0 +1,45 @@ +/** + * @name Ignoring result from pure array method + * @description Ignoring the result of an array method that does not modify its receiver is generally an error. + * @kind problem + * @problem.severity warning + * @id js/ignore-array-result + * @tags maintainability + * correctness + * @precision high + */ + +import javascript +import Expressions.ExprHasNoEffect + +DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) { + isIgnoredPureArrayCall(call) and + t.start() and + result = call.getReceiver().getALocalSource() + or + exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) +} + +DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) { + result = callsArray(DataFlow::TypeBackTracker::end(), call) +} + +predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) { + inVoidContext(call.asExpr()) and + ( + call.getMethodName() = "concat" and + call.getNumArgument() = 1 + or + call.getMethodName() = "join" and + call.getNumArgument() < 2 + or + call.getMethodName() = "slice" and + call.getNumArgument() < 3 + ) +} + +from DataFlow::MethodCallNode call +where + callsArray(call) instanceof DataFlow::ArrayCreationNode and + not call.getReceiver().asExpr().(ArrayExpr).getSize() = 0 +select call, "Result from call to " + call.getMethodName() + " ignored." diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index c586cfe2497..123515a7cbd 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -82,17 +82,138 @@ predicate alwaysThrows(Function f) { ) } -from DataFlow::CallNode call -where - not call.isIndefinite(_) and - forex(Function f | f = call.getACallee() | +/** + * Holds if the last statement in the function is flagged by the js/useless-expression query. + */ +predicate lastStatementHasNoEffect(Function f) { + hasNoEffect(f.getExit().getAPredecessor()) +} + +/** + * Holds if `func` is a callee of `call`, and all possible callees of `call` never return a value. + */ +predicate callToVoidFunction(DataFlow::CallNode call, Function func) { + not call.isIncomplete() and + func = call.getACallee() and + forall(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f) and not alwaysThrows(f) + ) +} + +/** + * Holds if `name` is the name of a method from `Array.prototype` or Lodash, + * where that method takes a callback as parameter, + * and the callback is expected to return a value. + */ +predicate hasNonVoidCallbackMethod(string name) { + name = "every" or + name = "filter" or + name = "find" or + name = "findIndex" or + name = "flatMap" or + name = "map" or + name = "reduce" or + name = "reduceRight" or + name = "some" or + name = "sort" +} + +DataFlow::SourceNode array(DataFlow::TypeTracker t) { + t.start() and result instanceof DataFlow::ArrayCreationNode + or + exists (DataFlow::TypeTracker t2 | + result = array(t2).track(t2, t) + ) +} + +DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } + +/** + * Holds if `call` is an Array or Lodash method accepting a callback `func`, + * where the `call` expects a callback that returns an expression, + * but `func` does not return a value. + */ +predicate voidArrayCallback(DataFlow::CallNode call, Function func) { + hasNonVoidCallbackMethod(call.getCalleeName()) and + exists(int index | + index = min(int i | exists(call.getCallback(i))) and + func = call.getCallback(index).getFunction() + ) and + returnsVoid(func) and + not isStub(func) and + not alwaysThrows(func) and + ( + call.getReceiver().getALocalSource() = array() + or + call.getCalleeNode().getALocalSource() instanceof LodashUnderscore::Member + ) +} + + +/** + * Provides classes for working with various Deferred implementations. + * It is a heuristic. The heuristic assume that a class is a promise defintion + * if the class is called "Deferred" and the method `resolve` is called on an instance. + * + * Removes some false positives in the js/use-of-returnless-function query. + */ +module Deferred { + /** + * An instance of a `Deferred` class. + * For example the result from `new Deferred()` or `new $.Deferred()`. + */ + class DeferredInstance extends DataFlow::NewNode { + // Describes both `new Deferred()`, `new $.Deferred` and other variants. + DeferredInstance() { this.getCalleeName() = "Deferred" } + + private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { + t.start() and + result = this + or + exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + } + + DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + } + + /** + * A promise object created by a Deferred constructor + */ + private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { + DeferredPromiseDefinition() { + // hardening of the "Deferred" heuristic: a method call to `resolve`. + exists(ref().getAMethodCall("resolve")) + } + + override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } + } + + /** + * A resolved promise created by a `new Deferred().resolve()` call. + */ + class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { + ResolvedDeferredPromiseDefinition() { + this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") + } + + override DataFlow::Node getValue() { result = getArgument(0) } + } +} + +from DataFlow::CallNode call, Function func, string name, string msg +where + ( + callToVoidFunction(call, func) and + msg = "the $@ does not return anything, yet the return value is used." and + name = func.describe() + or + voidArrayCallback(call, func) and + msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and + name = "callback function" ) and - not benignContext(call.asExpr()) and - + not lastStatementHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select - call, "the function $@ does not return anything, yet the return value is used.", call.getACallee(), call.getCalleeName() - + call, msg, func, name diff --git a/javascript/ql/src/Statements/examples/IgnoreArrayResult.js b/javascript/ql/src/Statements/examples/IgnoreArrayResult.js new file mode 100644 index 00000000000..7137d5261a6 --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreArrayResult.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js b/javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js new file mode 100644 index 00000000000..1c7977e9ef0 --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr = arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 9e75e032b1c..a6df138c592 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -28,6 +28,7 @@ import semmle.javascript.Functions import semmle.javascript.GlobalAccessPaths import semmle.javascript.HTML import semmle.javascript.HtmlSanitizers +import semmle.javascript.InclusionTests import semmle.javascript.JSDoc import semmle.javascript.JSON import semmle.javascript.JsonParsers diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index efc9ef53af3..66a5155458c 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -150,7 +150,7 @@ class TopLevel extends @toplevel, StmtContainer { /** Holds if this toplevel is minified. */ predicate isMinified() { // file name contains 'min' (not as part of a longer word) - getFile().getBaseName().regexpMatch(".*[^-.]*[-.]min([-.].*)?\\.\\w+") + getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+") or exists(int numstmt | numstmt = strictcount(Stmt s | s.getTopLevel() = this) | // there are more than two statements per line on average diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/src/semmle/javascript/Closure.qll index 066f68ca5fa..83b8049d48f 100644 --- a/javascript/ql/src/semmle/javascript/Closure.qll +++ b/javascript/ql/src/semmle/javascript/Closure.qll @@ -230,7 +230,7 @@ module Closure { * Gets the closure namespace path addressed by the given data flow node, if any. */ string getClosureNamespaceFromSourceNode(DataFlow::SourceNode node) { - result = GlobalAccessPath::getAccessPath(node) and + node = AccessPath::getAReferenceOrAssignmentTo(result) and hasClosureNamespacePrefix(result) } @@ -238,7 +238,7 @@ module Closure { * Gets the closure namespace path written to by the given property write, if any. */ string getWrittenClosureNamespace(DataFlow::PropWrite node) { - result = GlobalAccessPath::fromRhs(node.getRhs()) and + node.getRhs() = AccessPath::getAnAssignmentTo(result) and hasClosureNamespacePrefix(result) } diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 9e089fc9cf0..b19a19482d1 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -4,7 +4,55 @@ import javascript +deprecated module GlobalAccessPath { + /** + * DEPRECATED. Instead use `AccessPath::getAReferenceTo` with the result and parameter reversed. + */ + pragma[inline] + string fromReference(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) + } + + /** + * DEPRECATED. Instead use `AccessPath::getAnAssignmentTo` with the result and parameter reversed. + */ + pragma[inline] + string fromRhs(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) + } + + /** + * DEPRECATED. Use `AccessPath::getAReferenceOrAssignmentTo`. + */ + pragma[inline] + string getAccessPath(DataFlow::Node node) { + result = fromReference(node) + or + not exists(fromReference(node)) and + result = fromRhs(node) + } +} + +module AccessPath { + /** + * A source node that can be the root of an access path. + */ + class Root extends DataFlow::SourceNode { + Root() { + not this.accessesGlobal(_) and + not this instanceof DataFlow::PropRead and + not this instanceof PropertyProjection and + not this instanceof Closure::ClosureNamespaceAccess and + not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter()) + } + + /** Holds if this represents the root of the global access path. */ + predicate isGlobal() { + this = DataFlow::globalAccessPathRootPseudoNode() + } + } + /** * A local variable with exactly one definition, not counting implicit initialization. */ @@ -21,52 +69,68 @@ module GlobalAccessPath { } /** - * Gets the global access path referred to by `node`. + * Appends a single property name onto the access path `base`, where + * the empty string represents the empty access path. + */ + bindingset[base, prop] + private string join(string base, string prop) { + base = "" and result = prop + or + base != "" and + result = base + "." + prop + } + + /** + * Gets the access path relative to `root` referred to by `node`. * * This holds for direct references as well as for aliases * established through local data flow. * * Examples: * ``` - * function f() { - * let v = foo.bar; // reference to 'foo.bar' - * v.baz; // reference to 'foo.bar.baz' + * function f(x) { + * let a = x.f.g; // access path relative to 'x' is 'f.g' + * let b = a.h; // access path relative to 'x' is 'f.g.h' * } - * - * (function(ns) { - * ns.x; // reference to 'NS.x' - * })(NS = NS || {}); * ``` */ cached - string fromReference(DataFlow::Node node) { - result = fromReference(node.getImmediatePredecessor()) + private string fromReference(DataFlow::Node node, Root root) { + root = node and + not root.isGlobal() and + result = "" + or + result = fromReference(node.getImmediatePredecessor(), root) or exists(EffectivelyConstantVariable var | var.isCaptured() and node.asExpr() = var.getAnAccess() and - result = fromReference(var.getValue()) + result = fromReference(var.getValue(), root) ) or node.accessesGlobal(result) and - result != "undefined" + result != "undefined" and + root.isGlobal() or not node.accessesGlobal(_) and exists(DataFlow::PropRead prop | node = prop | - result = fromReference(prop.getBase()) + "." + prop.getPropertyName() + result = join(fromReference(prop.getBase(), root), prop.getPropertyName()) ) or - exists(Closure::ClosureNamespaceAccess acc | node = acc | result = acc.getClosureNamespace()) + exists(Closure::ClosureNamespaceAccess acc | node = acc | + result = acc.getClosureNamespace() and + root.isGlobal() + ) or exists(PropertyProjection proj | node = proj | proj.isSingletonProjection() and - result = fromReference(proj.getObject()) + "." + proj.getASelector() + result = join(fromReference(proj.getObject(), root), proj.getASelector().getStringValue()) ) or // Treat 'e || {}' as having the same name as 'e' exists(LogOrExpr e | node.asExpr() = e | e.getRightOperand().(ObjectExpr).getNumProperty() = 0 and - result = fromReference(e.getLeftOperand().flow()) + result = fromReference(e.getLeftOperand().flow(), root) ) or // Treat 'e && e.f' as having the same name as 'e.f' @@ -84,7 +148,7 @@ module GlobalAccessPath { rhs.getBase().(PropAccess).getQualifiedName() = name ) ) and - result = fromReference(rhs.flow()) + result = fromReference(rhs.flow(), root) ) } @@ -96,15 +160,17 @@ module GlobalAccessPath { * foo = foo || {}; * ``` */ - private predicate isSelfAssignment(DataFlow::Node rhs) { fromRhs(rhs) = fromReference(rhs) } + private predicate isSelfAssignment(DataFlow::Node rhs) { + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = fromReference(rhs, DataFlow::globalAccessPathRootPseudoNode()) + } /** - * Holds if there is an assignment to `accessPath` in `file`, not counting + * Holds if there is an assignment to the global `accessPath` in `file`, not counting * self-assignments. */ private predicate isAssignedInFile(string accessPath, File file) { exists(DataFlow::Node rhs | - fromRhs(rhs) = accessPath and + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = accessPath and not isSelfAssignment(rhs) and // Note: Avoid unneeded materialization of DataFlow::Node.getFile() rhs.getAstNode().getFile() = file @@ -112,7 +178,7 @@ module GlobalAccessPath { } /** - * Holds if `accessPath` is only assigned to from one file, not counting + * Holds if the global `accessPath` is only assigned to from one file, not counting * self-assignments. */ predicate isAssignedInUniqueFile(string accessPath) { @@ -120,66 +186,179 @@ module GlobalAccessPath { } /** - * Gets the global access path `node` is being assigned to, if any. + * Gets the access path relative to `root`, which `node` is being assigned to, if any. * * Only holds for the immediate right-hand side of an assignment or property, not * for nodes that transitively flow there. * - * For example, the class nodes below all map to `foo.bar`: + * For example, the class nodes below all map to `foo.bar` relative to `x`: + * ``` + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } + * ``` + */ + cached + private string fromRhs(DataFlow::Node node, Root root) { + exists(DataFlow::PropWrite write, string baseName | + node = write.getRhs() and + result = join(baseName, write.getPropertyName()) + | + baseName = fromReference(write.getBase(), root) + or + baseName = fromRhs(write.getBase(), root) + ) + or + exists(GlobalVariable var | + node = var.getAnAssignedExpr().flow() and + result = var.getName() and + root.isGlobal() + ) + or + exists(FunctionDeclStmt fun | + node = DataFlow::valueNode(fun) and + result = fun.getId().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(ClassDeclStmt cls | + node = DataFlow::valueNode(cls) and + result = cls.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(EnumDeclaration decl | + node = DataFlow::valueNode(decl) and + result = decl.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() + ) + or + exists(NamespaceDeclaration decl | + node = DataFlow::valueNode(decl) and + result = decl.getId().(GlobalVarDecl).getName() and + root.isGlobal() + ) + } + + /** + * Gets a node that refers to the given access path relative to the given `root` node, + * or `root` itself if the access path is empty. + * + * This works for direct references as well as for aliases established through local data flow. + * + * For example: + * ``` + * function f(x) { + * let a = x.f.g; // reference to (x, "f.g") + * let b = a.h; // reference to (x, "f.g.h") + * } + * ``` + */ + DataFlow::Node getAReferenceTo(Root root, string path) { + path = fromReference(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that refers to the given global access path. + * + * This works for direct references as well as for aliases established through local data flow. + * + * Examples: + * ``` + * function f() { + * let v = foo.bar; // reference to 'foo.bar' + * v.baz; // reference to 'foo.bar.baz' + * } + * + * (function(ns) { + * ns.x; // reference to 'NS.x' + * })(NS = NS || {}); + * ``` + */ + DataFlow::Node getAReferenceTo(string path) { + path = fromReference(result, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Gets a node that is assigned to the given access path relative to the given `root` node. + * + * Only gets the immediate right-hand side of an assignment or property, not + * nodes that transitively flow there. + * + * For example, the class nodes below are all assignments to `(x, "foo.bar")`. + * ``` + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } + * ``` + */ + DataFlow::Node getAnAssignmentTo(Root root, string path) { + path = fromRhs(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that is assigned to the given global access path. + * + * Only gets the immediate right-hand side of an assignment or property or a global declaration, + * not nodes that transitively flow there. + * + * For example, the class nodes below are all assignmetns to `foo.bar`: * ``` * foo.bar = class {}; - * * foo = { bar: class {} }; - * * (function(f) { * f.bar = class {} * })(foo = foo || {}); * ``` */ - cached - string fromRhs(DataFlow::Node node) { - exists(DataFlow::SourceNode base, string baseName, string name | - node = base.getAPropertyWrite(name).getRhs() and - result = baseName + "." + name - | - baseName = fromReference(base) - or - baseName = fromRhs(base) - ) - or - exists(GlobalVariable var | - node = var.getAnAssignedExpr().flow() and - result = var.getName() - ) - or - exists(FunctionDeclStmt fun | - node = DataFlow::valueNode(fun) and - result = fun.getId().(GlobalVarDecl).getName() - ) - or - exists(ClassDeclStmt cls | - node = DataFlow::valueNode(cls) and - result = cls.getIdentifier().(GlobalVarDecl).getName() - ) - or - exists(EnumDeclaration decl | - node = DataFlow::valueNode(decl) and - result = decl.getIdentifier().(GlobalVarDecl).getName() - ) - or - exists(NamespaceDeclaration decl | - node = DataFlow::valueNode(decl) and - result = decl.getId().(GlobalVarDecl).getName() - ) + DataFlow::Node getAnAssignmentTo(string path) { + path = fromRhs(result, DataFlow::globalAccessPathRootPseudoNode()) } /** - * Gets the global access path referenced by or assigned to `node`. + * Gets a node that refers to or is assigned to the given global access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ - string getAccessPath(DataFlow::Node node) { - result = fromReference(node) + DataFlow::Node getAReferenceOrAssignmentTo(string path) { + result = getAReferenceTo(path) or - not exists(fromReference(node)) and - result = fromRhs(node) + result = getAnAssignmentTo(path) + } + + /** + * Gets a node that refers to or is assigned to the given access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. + */ + DataFlow::Node getAReferenceOrAssignmentTo(Root root, string path) { + result = getAReferenceTo(root, path) + or + result = getAnAssignmentTo(root, path) + } + + /** + * Holds if there is a step from `pred` to `succ` through an assignment to an access path. + */ + pragma[inline] + predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(string name, Root root | + pred = getAnAssignmentTo(root, name) and + succ = getAReferenceTo(root, name) + ) + or + exists(string name | + pred = getAnAssignmentTo(name) and + succ = getAReferenceTo(name) and + isAssignedInUniqueFile(name) + ) } } diff --git a/javascript/ql/src/semmle/javascript/InclusionTests.qll b/javascript/ql/src/semmle/javascript/InclusionTests.qll new file mode 100644 index 00000000000..7a90dbf1583 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/InclusionTests.qll @@ -0,0 +1,173 @@ +/** + * Contains classes for recognizing array and string inclusion tests. + */ +private import javascript + +/** + * A expression that checks if an element is contained in an array + * or is a substring of another string. + * + * Examples: + * ``` + * A.includes(B) + * A.indexOf(B) !== -1 + * A.indexOf(B) >= 0 + * ~A.indexOf(B) + * ``` + */ +class InclusionTest extends DataFlow::Node { + InclusionTest::Range range; + + InclusionTest() { this = range } + + /** Gets the `A` in `A.includes(B)`. */ + DataFlow::Node getContainerNode() { result = range.getContainerNode() } + + /** Gets the `B` in `A.includes(B)`. */ + DataFlow::Node getContainedNode() { result = range.getContainedNode() } + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = range.getPolarity() } +} + +module InclusionTest { + /** + * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. + * + * Note that this also includes calls to the array method named `includes`. + */ + abstract class Range extends DataFlow::Node { + /** Gets the `A` in `A.includes(B)`. */ + abstract DataFlow::Node getContainerNode(); + + /** Gets the `B` in `A.includes(B)`. */ + abstract DataFlow::Node getContainedNode(); + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = true } + } + + /** + * A call to a method named `includes`, assumed to refer to `String.prototype.includes` + * or `Array.prototype.includes`. + */ + private class Includes_Native extends Range, DataFlow::MethodCallNode { + Includes_Native() { + getMethodName() = "includes" and + getNumArgument() = 1 + } + + override DataFlow::Node getContainerNode() { result = getReceiver() } + + override DataFlow::Node getContainedNode() { result = getArgument(0) } + } + + /** + * A call to `_.includes` or similar, assumed to operate on strings. + */ + private class Includes_Library extends Range, DataFlow::CallNode { + Includes_Library() { + exists(string name | + this = LodashUnderscore::member(name).getACall() and + (name = "includes" or name = "include" or name = "contains") + or + this = Closure::moduleImport("goog.string." + name).getACall() and + (name = "contains" or name = "caseInsensitiveContains") + ) + } + + override DataFlow::Node getContainerNode() { result = getArgument(0) } + + override DataFlow::Node getContainedNode() { result = getArgument(1) } + } + + /** + * A check of form `A.indexOf(B) !== -1` or similar. + */ + private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override EqualityTest astNode; + + Includes_IndexOfEquals() { + exists(Expr index | astNode.hasOperands(indexOf, index) | + // one operand is of the form `whitelist.indexOf(x)` + indexOf.getMethodName() = "indexOf" and + // and the other one is -1 + index.getIntValue() = -1 + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } + } + + /** + * A check of form `A.indexOf(B) >= 0` or similar. + */ + private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override RelationalComparison astNode; + boolean polarity; + + Includes_IndexOfRelational() { + exists(Expr lesser, Expr greater | + astNode.getLesserOperand() = lesser and + astNode.getGreaterOperand() = greater and + indexOf.getMethodName() = "indexOf" and + indexOf.getNumArgument() = 1 + | + polarity = true and + greater = indexOf and + ( + lesser.getIntValue() = 0 and astNode.isInclusive() + or + lesser.getIntValue() = -1 and not astNode.isInclusive() + ) + or + polarity = false and + lesser = indexOf and + ( + greater.getIntValue() = -1 and astNode.isInclusive() + or + greater.getIntValue() = 0 and not astNode.isInclusive() + ) + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = polarity } + } + + /** + * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. + */ + private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override BitNotExpr astNode; + + Includes_IndexOfBitwise() { + astNode.getOperand() = indexOf and + indexOf.getMethodName() = "indexOf" + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + } +} diff --git a/javascript/ql/src/semmle/javascript/JSDoc.qll b/javascript/ql/src/semmle/javascript/JSDoc.qll index 806a9477ba6..c080061bc7c 100644 --- a/javascript/ql/src/semmle/javascript/JSDoc.qll +++ b/javascript/ql/src/semmle/javascript/JSDoc.qll @@ -582,7 +582,7 @@ module JSDoc { * within this container. */ string resolveAlias(string alias) { - result = GlobalAccessPath::getAccessPath(getNodeFromAlias(alias)) + getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result) } /** diff --git a/javascript/ql/src/semmle/javascript/StringOps.qll b/javascript/ql/src/semmle/javascript/StringOps.qll index f33dbd9f74d..d916e8e469d 100644 --- a/javascript/ql/src/semmle/javascript/StringOps.qll +++ b/javascript/ql/src/semmle/javascript/StringOps.qll @@ -185,162 +185,15 @@ module StringOps { /** * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. * - * Note that this also includes calls to the array method named `includes`. + * Note that this class is equivalent to `InclusionTest`, which also matches + * inclusion tests on array objects. */ - class Includes extends DataFlow::Node { - Includes::Range range; - - Includes() { this = range } - + class Includes extends InclusionTest { /** Gets the `A` in `A.includes(B)`. */ - DataFlow::Node getBaseString() { result = range.getBaseString() } + DataFlow::Node getBaseString() { result = getContainerNode() } /** Gets the `B` in `A.includes(B)`. */ - DataFlow::Node getSubstring() { result = range.getSubstring() } - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = range.getPolarity() } - } - - module Includes { - /** - * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. - * - * Note that this also includes calls to the array method named `includes`. - */ - abstract class Range extends DataFlow::Node { - /** Gets the `A` in `A.includes(B)`. */ - abstract DataFlow::Node getBaseString(); - - /** Gets the `B` in `A.includes(B)`. */ - abstract DataFlow::Node getSubstring(); - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = true } - } - - /** - * A call to a method named `includes`, assumed to refer to `String.prototype.includes`. - */ - private class Includes_Native extends Range, DataFlow::MethodCallNode { - Includes_Native() { - getMethodName() = "includes" and - getNumArgument() = 1 - } - - override DataFlow::Node getBaseString() { result = getReceiver() } - - override DataFlow::Node getSubstring() { result = getArgument(0) } - } - - /** - * A call to `_.includes` or similar, assumed to operate on strings. - */ - private class Includes_Library extends Range, DataFlow::CallNode { - Includes_Library() { - exists(string name | - this = LodashUnderscore::member(name).getACall() and - (name = "includes" or name = "include" or name = "contains") - or - this = Closure::moduleImport("goog.string." + name).getACall() and - (name = "contains" or name = "caseInsensitiveContains") - ) - } - - override DataFlow::Node getBaseString() { result = getArgument(0) } - - override DataFlow::Node getSubstring() { result = getArgument(1) } - } - - /** - * A check of form `A.indexOf(B) !== -1` or similar. - */ - private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override EqualityTest astNode; - - Includes_IndexOfEquals() { - exists(Expr index | astNode.hasOperands(indexOf, index) | - // one operand is of the form `whitelist.indexOf(x)` - indexOf.getMethodName() = "indexOf" and - // and the other one is -1 - index.getIntValue() = -1 - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } - } - - /** - * A check of form `A.indexOf(B) >= 0` or similar. - */ - private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override RelationalComparison astNode; - boolean polarity; - - Includes_IndexOfRelational() { - exists(Expr lesser, Expr greater | - astNode.getLesserOperand() = lesser and - astNode.getGreaterOperand() = greater and - indexOf.getMethodName() = "indexOf" and - indexOf.getNumArgument() = 1 - | - polarity = true and - greater = indexOf and - ( - lesser.getIntValue() = 0 and astNode.isInclusive() - or - lesser.getIntValue() = -1 and not astNode.isInclusive() - ) - or - polarity = false and - lesser = indexOf and - ( - greater.getIntValue() = -1 and astNode.isInclusive() - or - greater.getIntValue() = 0 and not astNode.isInclusive() - ) - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = polarity } - } - - /** - * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. - */ - private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override BitNotExpr astNode; - - Includes_IndexOfBitwise() { - astNode.getOperand() = indexOf and - indexOf.getMethodName() = "indexOf" - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - } + DataFlow::Node getSubstring() { result = getContainedNode() } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll new file mode 100644 index 00000000000..caf67e6db7f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll @@ -0,0 +1,44 @@ +/** + * Provides machinery for performing backward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSource` predicate. Instead, flow is tracked from any _initial node_ (that is, + * a node without incoming flow) to a sink node. All initial nodes are then treated as source + * nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. Backward + * exploration in particular does not scale on non-trivial code bases and hence is of limited + * usefulness as it stands. + */ + +import javascript + +private class BackwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + BackwardExploringConfiguration() { + this = cfg + } + + override predicate isSource(DataFlow::Node node) { any() } + + override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode first | + source.getConfiguration() = this and + source.getASuccessor() = first and + not exists(DataFlow::MidPathNode mid | mid.getASuccessor() = first) and + first.getASuccessor*() = sink + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 568c1c92eab..11cfb24376e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -147,7 +147,7 @@ abstract class Configuration extends string { */ predicate isBarrier(DataFlow::Node node) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, "") ) } @@ -181,7 +181,7 @@ abstract class Configuration extends string { */ predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, lbl) ) or @@ -198,6 +198,12 @@ abstract class Configuration extends string { */ predicate isBarrierGuard(BarrierGuardNode guard) { none() } + private predicate isBarrierGuardInternal(BarrierGuardNode guard) { + isBarrierGuard(guard) + or + guard.(AdditionalBarrierGuardNode).appliesTo(this) + } + /** * Holds if data may flow from `source` to `sink` for this configuration. */ @@ -302,42 +308,27 @@ abstract class BarrierGuardNode extends DataFlow::Node { exists(SsaRefinementNode ref, boolean outcome | nd = DataFlow::ssaDefinitionNode(ref) and forex(SsaVariable input | input = ref.getAnInput() | - asExpr() = ref.getGuard().getTest() and + getExpr() = ref.getGuard().getTest() and outcome = ref.getGuard().(ConditionGuardNode).getOutcome() and - internalBlocksExpr(outcome, input.getAUse(), label) + barrierGuardBlocksExpr(this, outcome, input.getAUse(), label) ) ) or // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p` exists(AccessPath p, BasicBlock bb, ConditionGuardNode cond, boolean outcome | nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and - asExpr() = cond.getTest() and + getExpr() = cond.getTest() and outcome = cond.getOutcome() and - internalBlocksAccessPath(outcome, p, label) and + barrierGuardBlocksAccessPath(this, outcome, p, label) and cond.dominates(bb) ) } - /** - * Holds if data flow node `nd` acts as a barrier for data flow. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - private predicate internalBlocksExpr(boolean outcome, Expr test, string label) { - blocks(outcome, test) and label = "" + /** Gets the corresponding expression, including that of reflective calls. */ + private Expr getExpr() { + result = asExpr() or - blocks(outcome, test, label) - } - - /** - * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through - * an access path. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - pragma[noinline] - private predicate internalBlocksAccessPath(boolean outcome, AccessPath ap, string label) { - internalBlocksExpr(outcome, ap.getAnInstance(), label) + this = DataFlow::reflectiveCallNode(result) } /** @@ -353,6 +344,32 @@ abstract class BarrierGuardNode extends DataFlow::Node { predicate blocks(boolean outcome, Expr e, FlowLabel label) { none() } } +/** + * Holds if data flow node `nd` acts as a barrier for data flow. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +private predicate barrierGuardBlocksExpr(BarrierGuardNode guard, boolean outcome, Expr test, string label) { + guard.blocks(outcome, test) and label = "" + or + guard.blocks(outcome, test, label) + or + // Handle labelled barrier guard functions specially, to avoid negative recursion + // through the non-abstract 3-argument version of blocks(). + guard.(AdditionalBarrierGuardCall).internalBlocksLabel(outcome, test, label) +} + +/** + * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through + * an access path. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +pragma[noinline] +private predicate barrierGuardBlocksAccessPath(BarrierGuardNode guard, boolean outcome, AccessPath ap, string label) { + barrierGuardBlocksExpr(guard, outcome, ap.getAnInstance(), label) +} + /** * A guard node that only blocks specific labels. */ @@ -1186,3 +1203,110 @@ module PathGraph { not pred = finalMidNode(succ) } } + + + +/** + * Gets an operand of the given `&&` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalAndOperand(LogAndExpr e) { + result = e.getAnOperand() +} + +/** + * Gets an operand of the given `||` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalOrOperand(LogOrExpr e) { + result = e.getAnOperand() +} + +/** + * A `BarrierGuardNode` that controls which data flow + * configurations it is used in. + * + * Note: For performance reasons, all subclasses of this class should be part + * of the standard library. Override `Configuration::isBarrierGuard` + * for analysis-specific barrier guards. + */ +abstract class AdditionalBarrierGuardNode extends BarrierGuardNode { + abstract predicate appliesTo(Configuration cfg); +} + +/** + * A function that returns the result of a barrier guard. + */ +private class BarrierGuardFunction extends Function { + DataFlow::ParameterNode sanitizedParameter; + BarrierGuardNode guard; + boolean guardOutcome; + string label; + + BarrierGuardFunction() { + exists(Expr e | + exists(Expr returnExpr | + returnExpr = guard.asExpr() + or + // ad hoc support for conjunctions: + getALogicalAndOperand+(returnExpr) = guard.asExpr() and guardOutcome = true + or + // ad hoc support for disjunctions: + getALogicalOrOperand+(returnExpr) = guard.asExpr() and guardOutcome = false + | + exists(SsaExplicitDefinition ssa | + ssa.getDef().getSource() = returnExpr and + ssa.getVariable().getAUse() = getAReturnedExpr() + ) + or + returnExpr = getAReturnedExpr() + ) and + sanitizedParameter.flowsToExpr(e) and + barrierGuardBlocksExpr(guard, guardOutcome, e, label) + ) and + getNumParameter() = 1 and + sanitizedParameter.getParameter() = getParameter(0) + } + + /** + * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. + */ + predicate isBarrierCall(DataFlow::CallNode call, Expr e, boolean outcome, string lbl) { + exists(DataFlow::Node arg | + arg.asExpr() = e and + arg = call.getArgument(0) and + call.getNumArgument() = 1 and + argumentPassing(call, arg, this, sanitizedParameter) and + outcome = guardOutcome and + lbl = label + ) + } + + /** + * Holds if this function applies to the flow in `cfg`. + */ + predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(guard) } +} + +/** + * A call that sanitizes an argument. + */ +private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, DataFlow::CallNode { + BarrierGuardFunction f; + + AdditionalBarrierGuardCall() { f.isBarrierCall(this, _, _, _) } + + override predicate blocks(boolean outcome, Expr e) { + f.isBarrierCall(this, e, outcome, "") + } + + predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel label) { + f.isBarrierCall(this, e, outcome, label) + } + + override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37..ddd52239f8d 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -188,11 +188,7 @@ module DataFlow { lvalueFlowStep(result, this) and not lvalueDefaultFlowStep(_, this) or - // Use of variable -> definition of variable - exists(SsaVariable var | - this = valueNode(var.getAUse()) and - result = TSsaDefNode(var) - ) + immediateFlowStep(result, this) or // Refinement of variable -> original definition of variable exists(SsaRefinementNode refinement | @@ -741,7 +737,8 @@ module DataFlow { PropReadAsSourceNode() { this = TPropNode(any(PropertyPattern p)) or this instanceof RestPatternNode or - this instanceof ElementPatternNode + this instanceof ElementPatternNode or + this = lvalueNode(any(ForOfStmt stmt).getLValue()) } } @@ -826,6 +823,24 @@ module DataFlow { override string getPropertyName() { result = astNode.getImportedName() } } + /** + * The left-hand side of a `for..of` statement, seen as a property read + * on the object being iterated over. + */ + private class ForOfLvalueAsPropRead extends PropRead { + ForOfStmt stmt; + + ForOfLvalueAsPropRead() { + this = lvalueNode(stmt.getLValue()) + } + + override Node getBase() { result = stmt.getIterationDomain().flow() } + + override Expr getPropertyNameExpr() { none() } + + override string getPropertyName() { none() } + } + /** * A data flow node representing an unused parameter. * @@ -932,6 +947,15 @@ module DataFlow { */ DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot } + /** + * Gets a data flow node representing the underlying call performed by the given + * call to `Function.prototype.call` or `Function.prototype.apply`. + * + * For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the + * callee, `x` as the receiver, and `y` as the first argument. + */ + DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) } + /** * Provides classes representing various kinds of calls. * @@ -1299,6 +1323,44 @@ module DataFlow { ) } + /** + * Flow steps shared between `getImmediatePredecessor` and `localFlowStep`. + * + * Inlining is forced because the two relations are indexed differently. + */ + pragma[inline] + private predicate immediateFlowStep(Node pred, Node succ) { + exists(SsaVariable v | + pred = TSsaDefNode(v.getDefinition()) and + succ = valueNode(v.getAUse()) + ) + or + exists(Expr predExpr, Expr succExpr | + pred = valueNode(predExpr) and succ = valueNode(succExpr) + | + predExpr = succExpr.(ParExpr).getExpression() + or + predExpr = succExpr.(SeqExpr).getLastOperand() + or + predExpr = succExpr.(AssignExpr).getRhs() + or + predExpr = succExpr.(TypeAssertion).getExpression() + or + predExpr = succExpr.(NonNullAssertion).getExpression() + or + predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() + ) + or + // flow from 'this' parameter into 'this' expressions + exists(ThisExpr thiz | + pred = TThisNode(thiz.getBindingContainer()) and + succ = valueNode(thiz) + ) + or + // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform + pred = TReflectiveCallNode(succ.asExpr(), _) + } + /** * Holds if data can flow from `pred` to `succ` in one local step. */ @@ -1309,6 +1371,8 @@ module DataFlow { or lvalueDefaultFlowStep(pred, succ) or + immediateFlowStep(pred, succ) + or // Flow through implicit SSA nodes exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) | // from any explicit definition or implicit init of a captured variable into @@ -1326,45 +1390,18 @@ module DataFlow { pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition()) ) or - // flow out of local variables - exists(SsaVariable v | - pred = TSsaDefNode(v.getDefinition()) and - succ = valueNode(v.getAUse()) - ) - or exists(Expr predExpr, Expr succExpr | pred = valueNode(predExpr) and succ = valueNode(succExpr) | - predExpr = succExpr.(ParExpr).getExpression() - or - predExpr = succExpr.(SeqExpr).getLastOperand() - or predExpr = succExpr.(LogicalBinaryExpr).getAnOperand() or - predExpr = succExpr.(AssignExpr).getRhs() - or predExpr = succExpr.(ConditionalExpr).getABranch() or - predExpr = succExpr.(TypeAssertion).getExpression() - or - predExpr = succExpr.(NonNullAssertion).getExpression() - or - predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() - or exists(Function f | predExpr = f.getAReturnedExpr() and localCall(succExpr, f) ) ) - or - // flow from 'this' parameter into 'this' expressions - exists(ThisExpr thiz | - pred = TThisNode(thiz.getBindingContainer()) and - succ = valueNode(thiz) - ) - or - // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform - pred = TReflectiveCallNode(succ.asExpr(), _) } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll new file mode 100644 index 00000000000..0e3a7ae91c2 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll @@ -0,0 +1,42 @@ +/** + * Provides machinery for performing forward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSink` predicate. Instead, flow is tracked from source nodes as far as + * possible, until a _terminal node_ (that is, a node without any outgoing flow) is reached. + * All terminal nodes are then treated as sink nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. + */ + +import javascript + +private class ForwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + ForwardExploringConfiguration() { + this = cfg + } + + override predicate isSink(DataFlow::Node node) { any() } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode last | + source.getConfiguration() = this and + source.getASuccessor*() = last and + not last.getASuccessor() instanceof DataFlow::MidPathNode and + last.getASuccessor() = sink + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index a44f2909ce0..d06056a4696 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -771,11 +771,7 @@ class ClassNode extends DataFlow::SourceNode { */ pragma[noinline] predicate hasQualifiedName(string name) { - exists(DataFlow::Node rhs | - getAClassReference().flowsTo(rhs) and - name = GlobalAccessPath::fromRhs(rhs) and - GlobalAccessPath::isAssignedInUniqueFile(name) - ) + getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name)) } } @@ -883,7 +879,7 @@ module ClassNode { } private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { - GlobalAccessPath::getAccessPath(result.getBase()) = name and + result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and result.getPropertyName() = "prototype" and result.getFile() = f } @@ -904,7 +900,7 @@ module ClassNode { ) or exists(string name | - name = GlobalAccessPath::fromRhs(this) and + this = AccessPath::getAnAssignmentTo(name) and exists(getAPrototypeReferenceInFile(name, getFile())) ) ) @@ -969,7 +965,7 @@ module ClassNode { ) or exists(string name | - GlobalAccessPath::fromRhs(this) = name and + this = AccessPath::getAnAssignmentTo(name) and result = getAPrototypeReferenceInFile(name, getFile()) ) or diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 06a0d904261..24892805242 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -133,8 +133,8 @@ module TaintTracking { * configurations it is used in. * * Note: For performance reasons, all subclasses of this class should be part - * of the standard library. Override `Configuration::isSanitizer` - * for analysis-specific taint steps. + * of the standard library. Override `Configuration::isSanitizerGuard` + * for analysis-specific taint sanitizer guards. */ abstract class AdditionalSanitizerGuardNode extends SanitizerGuardNode { /** @@ -781,15 +781,18 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } - /** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */ - class StringInclusionSanitizer extends AdditionalSanitizerGuardNode { - StringOps::Includes includes; + /** DEPRECATED. This class has been renamed to `InclusionSanitizer`. */ + deprecated class StringInclusionSanitizer = InclusionSanitizer; - StringInclusionSanitizer() { this = includes } + /** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */ + class InclusionSanitizer extends AdditionalSanitizerGuardNode { + InclusionTest inclusion; + + InclusionSanitizer() { this = inclusion } override predicate sanitizes(boolean outcome, Expr e) { - outcome = includes.getPolarity() and - e = includes.getSubstring().asExpr() + outcome = inclusion.getPolarity() and + e = inclusion.getContainedNode().asExpr() } override predicate appliesTo(Configuration cfg) { any() } @@ -846,71 +849,6 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } - /** - * A function that returns the result of a sanitizer check. - */ - private class SanitizingFunction extends Function { - DataFlow::ParameterNode sanitizedParameter; - SanitizerGuardNode sanitizer; - boolean sanitizerOutcome; - - SanitizingFunction() { - exists(Expr e | - exists(Expr returnExpr | - returnExpr = sanitizer.asExpr() - or - // ad hoc support for conjunctions: - returnExpr.(LogAndExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = true - or - // ad hoc support for disjunctions: - returnExpr.(LogOrExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = false - | - exists(SsaExplicitDefinition ssa | - ssa.getDef().getSource() = returnExpr and - ssa.getVariable().getAUse() = getAReturnedExpr() - ) - or - returnExpr = getAReturnedExpr() - ) and - sanitizedParameter.flowsToExpr(e) and - sanitizer.sanitizes(sanitizerOutcome, e) - ) and - getNumParameter() = 1 and - sanitizedParameter.getParameter() = getParameter(0) - } - - /** - * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. - */ - predicate isSanitizingCall(DataFlow::CallNode call, Expr e, boolean outcome) { - exists(DataFlow::Node arg | - arg.asExpr() = e and - arg = call.getArgument(0) and - call.getNumArgument() = 1 and - FlowSteps::argumentPassing(call, arg, this, sanitizedParameter) and - outcome = sanitizerOutcome - ) - } - - /** - * Holds if this function applies to the flow in `cfg`. - */ - predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(sanitizer) } - } - - /** - * A call that sanitizes an argument. - */ - private class AdditionalSanitizingCall extends AdditionalSanitizerGuardNode, DataFlow::CallNode { - SanitizingFunction f; - - AdditionalSanitizingCall() { f.isSanitizingCall(this, _, _) } - - override predicate sanitizes(boolean outcome, Expr e) { f.isSanitizingCall(this, e, outcome) } - - override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } - } - /** * An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object, * considered as a sanitizer for `e`. diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index ef639d99ad4..ecbb3187728 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -13,7 +13,9 @@ private class PropertyName extends string { PropertyName() { this = any(DataFlow::PropRef pr).getPropertyName() or - GlobalAccessPath::isAssignedInUniqueFile(this) + AccessPath::isAssignedInUniqueFile(this) + or + exists(AccessPath::getAnAssignmentTo(_, this)) } } @@ -95,20 +97,35 @@ module StepSummary { any(AdditionalTypeTrackingStep st).step(pred, succ) and summary = LevelStep() or + // Store to global access path exists(string name | - name = GlobalAccessPath::fromRhs(pred) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + pred = AccessPath::getAnAssignmentTo(name) and + AccessPath::isAssignedInUniqueFile(name) and succ = DataFlow::globalAccessPathRootPseudoNode() and summary = StoreStep(name) ) or + // Load from global access path exists(string name | - name = GlobalAccessPath::fromReference(succ) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + succ = AccessPath::getAReferenceTo(name) and + AccessPath::isAssignedInUniqueFile(name) and pred = DataFlow::globalAccessPathRootPseudoNode() and summary = LoadStep(name) ) or + // Store to non-global access path + exists(string name | + pred = AccessPath::getAnAssignmentTo(succ, name) and + summary = StoreStep(name) + ) + or + // Load from non-global access path + exists(string name | + succ = AccessPath::getAReferenceTo(pred, name) and + summary = LoadStep(name) and + name != "" + ) + or // Summarize calls with flow directly from a parameter to a return. exists(DataFlow::ParameterNode param, DataFlow::FunctionNode fun | ( diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index a5e140734a4..d58a83fa0bd 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -43,11 +43,7 @@ module CallGraph { or imprecision = 0 and t.start() and - exists(string name | - GlobalAccessPath::isAssignedInUniqueFile(name) and - GlobalAccessPath::fromRhs(function) = name and - GlobalAccessPath::fromReference(result) = name - ) + AccessPath::step(function, result) or imprecision = 0 and exists(DataFlow::ClassNode cls | diff --git a/javascript/ql/test/library-tests/CFG/CFG.expected b/javascript/ql/test/library-tests/CFG/CFG.expected index 7904099cb44..a41f1c4999a 100644 --- a/javascript/ql/test/library-tests/CFG/CFG.expected +++ b/javascript/ql/test/library-tests/CFG/CFG.expected @@ -546,7 +546,7 @@ | classes | 39 | static x = 5; | 39 | t = cla ... () {} } | | classes | 39 | t | 39 | A | | classes | 39 | t = cla ... () {} } | 39 | t | -| classes | 39 | t = cla ... () {} } | 42 | exit node of | +| classes | 39 | t = cla ... () {} } | 40 | exit node of | | classes | 39 | x | 39 | 5 | | classes | 39 | {} | 39 | exit node of () {} | | decorated_parameter | 1 | C | 2 | foo | @@ -625,7 +625,7 @@ | fields | 8 | {} | 8 | exit node of () {} | | fields | 11 | A | 12 | constructor | | fields | 11 | B | 11 | A | -| fields | 11 | class B ... \\n z;\\n} | 21 | exit node of | +| fields | 11 | class B ... \\n z;\\n} | 19 | exit node of | | fields | 12 | constru ... er;\\n } | 11 | class B ... \\n z;\\n} | | fields | 12 | constructor | 12 | function in constru ... er;\\n } | | fields | 12 | entry node of () {\\n ... er;\\n } | 12 | {\\n b ... er;\\n } | @@ -680,7 +680,7 @@ | globals | 19 | h | 20 | {\\n} | | globals | 20 | {\\n} | 21 | exit node of function\\n h()\\n{\\n} | | mixedMembers | 1 | Mixed | 3 | constructor | -| mixedMembers | 1 | class M ... z) {}\\n} | 7 | exit node of | +| mixedMembers | 1 | class M ... z) {}\\n} | 6 | exit node of | | mixedMembers | 1 | entry node of | 1 | Mixed | | mixedMembers | 2 | 3 | 2 | x = 3 | | mixedMembers | 2 | x | 2 | 3 | @@ -746,7 +746,7 @@ | staticFields | 2 | C | 2 | new C() | | staticFields | 2 | instance | 2 | C | | staticFields | 2 | new C() | 2 | static ... ew C(); | -| staticFields | 2 | static ... ew C(); | 7 | exit node of | +| staticFields | 2 | static ... ew C(); | 4 | exit node of | | staticFieldsTS | 1 | C | 1 | constructor | | staticFieldsTS | 1 | class C ... C();\\n} | 2 | instance | | staticFieldsTS | 1 | constructor | 1 | function in constructor() {} | diff --git a/javascript/ql/test/library-tests/CFG/classes.js b/javascript/ql/test/library-tests/CFG/classes.js index cf4bedc2a3b..fa35da77f32 100644 --- a/javascript/ql/test/library-tests/CFG/classes.js +++ b/javascript/ql/test/library-tests/CFG/classes.js @@ -37,5 +37,3 @@ t = class extends A { f() {} } t = class extends A { x = 5; f() {} } t = class extends A { static x = 5; f() {} } t = class extends A { static x = 5; f() {} constructor() {} } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/fields.js b/javascript/ql/test/library-tests/CFG/fields.js index ef4b105c9ff..e93c13eaa18 100644 --- a/javascript/ql/test/library-tests/CFG/fields.js +++ b/javascript/ql/test/library-tests/CFG/fields.js @@ -16,5 +16,3 @@ class B extends A { } z; } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/mixedMembers.js b/javascript/ql/test/library-tests/CFG/mixedMembers.js index 33de7b7ff4a..8ff3721d61c 100644 --- a/javascript/ql/test/library-tests/CFG/mixedMembers.js +++ b/javascript/ql/test/library-tests/CFG/mixedMembers.js @@ -3,5 +3,3 @@ class Mixed { constructor(y) {} method(z) {} } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CFG/options b/javascript/ql/test/library-tests/CFG/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/CFG/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/staticFields.js b/javascript/ql/test/library-tests/CFG/staticFields.js index 5d8fc7605a2..fa3070ab19f 100644 --- a/javascript/ql/test/library-tests/CFG/staticFields.js +++ b/javascript/ql/test/library-tests/CFG/staticFields.js @@ -1,6 +1,3 @@ class C { static instance = new C(); } - -// semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js new file mode 100644 index 00000000000..f320d3ae8f4 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js @@ -0,0 +1,39 @@ +function foo() { + let self = this; + + /** name:direct */ + self.foo.bar.direct = function() {}; + + /** calls:direct */ + self.foo.bar.direct(); + + self.foo.bar = { + /** name:baz */ + baz() {}, + bong() { + /** calls:baz */ + self.foo.bar.baz(); + } + } + + /** calls:baz */ + self.foo.bar.baz(); + + self.foo.bar.Class = class { + /** name:m */ + m() {} + } + + self.foo.bar.instance = new self.foo.bar.Class(); + + /** calls:m */ + self.foo.bar.instance.m(); + + let unknownObject = unknownCall(); + + /** name:direct2 */ + unknownObject.bar.baz.direct = function() {}; + + /** calls:direct2 */ + unknownObject.bar.baz.direct(); +} diff --git a/javascript/ql/test/library-tests/Classes/fields.js b/javascript/ql/test/library-tests/Classes/fields.js index 63b701e48ac..f71520fc1f8 100644 --- a/javascript/ql/test/library-tests/Classes/fields.js +++ b/javascript/ql/test/library-tests/Classes/fields.js @@ -2,5 +2,3 @@ class C { x; y = 42 } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Classes/options b/javascript/ql/test/library-tests/Classes/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Classes/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js index 5194bcc9ddd..32b649bfdae 100644 --- a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js +++ b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js @@ -8,5 +8,3 @@ year; year; (for (i of numbers) for (j of letters) i+j); (for (i of numbers) for (j of letters) if (i x); })(23); /x/; + +function foo(array) { + for (let key of array) { key; } + for (let { key } of array) { key; } +} diff --git a/javascript/ql/test/library-tests/DataFlow/tst.js b/javascript/ql/test/library-tests/DataFlow/tst.js index 5de8e4e8688..319ca7fcb45 100644 --- a/javascript/ql/test/library-tests/DataFlow/tst.js +++ b/javascript/ql/test/library-tests/DataFlow/tst.js @@ -113,5 +113,3 @@ x ?? y; // flow through short-circuiting operator }); Array.call() // flow from implicit call to `Array` to `Array.call` - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DataFlow/tst.ts b/javascript/ql/test/library-tests/DataFlow/tst.ts index dca2ee632b7..29c85cba933 100644 --- a/javascript/ql/test/library-tests/DataFlow/tst.ts +++ b/javascript/ql/test/library-tests/DataFlow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); x; // global namespace exports are incompletely analysed @@ -11,5 +11,3 @@ function setX() { var nd2 = A.x as number; // flow through type assertions class StringList extends List {} // flow through expressions with type arguments - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/Decorators/options b/javascript/ql/test/library-tests/Decorators/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Decorators/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Decorators/tst.js b/javascript/ql/test/library-tests/Decorators/tst.js index 5b3f6432a00..d2135995168 100644 --- a/javascript/ql/test/library-tests/Decorators/tst.js +++ b/javascript/ql/test/library-tests/Decorators/tst.js @@ -7,5 +7,3 @@ var o = { get bar() { return 42 }, set bar(v) { } }; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/DefUse/es2015.js b/javascript/ql/test/library-tests/DefUse/es2015.js index 7bc60b605fc..2264f76cecc 100644 --- a/javascript/ql/test/library-tests/DefUse/es2015.js +++ b/javascript/ql/test/library-tests/DefUse/es2015.js @@ -4,5 +4,3 @@ for (let fn in fns) function getSquares() { return [for (i of [0, 1, 2]) i*i]; } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DefUse/options b/javascript/ql/test/library-tests/DefUse/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/DefUse/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Errors/options b/javascript/ql/test/library-tests/Errors/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/Errors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/setters.js b/javascript/ql/test/library-tests/Errors/setters.js index 50865e9f0c9..a8d40c45d2f 100644 --- a/javascript/ql/test/library-tests/Errors/setters.js +++ b/javascript/ql/test/library-tests/Errors/setters.js @@ -8,5 +8,3 @@ var o = { set y(...ys) {}, set z(z, ...zs) {} }; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/tst.js b/javascript/ql/test/library-tests/Errors/tst.js index baf2fbf4711..f0931ee0e49 100644 --- a/javascript/ql/test/library-tests/Errors/tst.js +++ b/javascript/ql/test/library-tests/Errors/tst.js @@ -1,4 +1,2 @@ while } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Expr/legacyletexpr.js b/javascript/ql/test/library-tests/Expr/legacyletexpr.js index d5d121d8a79..6e7eedff052 100644 --- a/javascript/ql/test/library-tests/Expr/legacyletexpr.js +++ b/javascript/ql/test/library-tests/Expr/legacyletexpr.js @@ -1,3 +1 @@ console.log(let (x = 23, y = 19) x + y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Expr/mozextensions.js b/javascript/ql/test/library-tests/Expr/mozextensions.js index 5c44146b42f..bab58100c65 100644 --- a/javascript/ql/test/library-tests/Expr/mozextensions.js +++ b/javascript/ql/test/library-tests/Expr/mozextensions.js @@ -1,3 +1 @@ array.map(function(x) x+1); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Expr/options b/javascript/ql/test/library-tests/Expr/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Expr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Expr/tests.expected b/javascript/ql/test/library-tests/Expr/tests.expected index 9757957cc39..1c3963b50ea 100644 --- a/javascript/ql/test/library-tests/Expr/tests.expected +++ b/javascript/ql/test/library-tests/Expr/tests.expected @@ -682,29 +682,29 @@ test_getTopLevel | functions.js:7:4:7:4 | x | functions.js:1:1:10:7 | | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:10:7 | | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:2:0 | | | nullSensitiveContexts.js:7:1:7:3 | foo | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:1:7:8 | foo[bar] | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:5:7:7 | bar | nullSensitiveContexts.js:1:1:61:0 | | @@ -1922,25 +1922,25 @@ test_getContainer | functions.js:7:4:7:4 | x | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | | mozextensions.js:1:20:1:20 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:23 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:11:1:25 | function(x) x+1 | diff --git a/javascript/ql/test/library-tests/Externs/Point.js b/javascript/ql/test/library-tests/Externs/Point.js index a811a482009..ea4c950e7d2 100644 --- a/javascript/ql/test/library-tests/Externs/Point.js +++ b/javascript/ql/test/library-tests/Externs/Point.js @@ -17,4 +17,4 @@ Point.prototype['final']; /** @type {!Point} */ var aPoint; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index 42117cac98a..531faf562bd 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -194,8 +194,8 @@ | n.js:2:1:2:15 | function g | | n.js:2:1:2:15 | instance of function g | | n.js:3:16:3:23 | object literal | -| namespace-reexport.js:1:1:4:0 | exports object of module namespace-reexport | -| namespace-reexport.js:1:1:4:0 | module object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | exports object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | module object of module namespace-reexport | | nestedImport.js:1:1:13:0 | exports object of module nestedImport | | nestedImport.js:1:1:13:0 | module object of module nestedImport | | nestedImport.js:9:1:12:1 | function tst | @@ -235,14 +235,14 @@ | objlit.js:43:12:45:3 | object literal | | reexport-d.js:1:1:2:0 | exports object of module reexport-d | | reexport-d.js:1:1:2:0 | module object of module reexport-d | -| reexport-mixins.js:1:1:4:0 | exports object of module reexport-mixins | -| reexport-mixins.js:1:1:4:0 | module object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | exports object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | module object of module reexport-mixins | | reexport-unknown.js:1:1:2:0 | exports object of module reexport-unknown | | reexport-unknown.js:1:1:2:0 | module object of module reexport-unknown | | reexport/client/src/index.js:1:1:3:0 | exports object of module index | | reexport/client/src/index.js:1:1:3:0 | module object of module index | -| reexport/lib/index.js:1:1:4:0 | exports object of module index | -| reexport/lib/index.js:1:1:4:0 | module object of module index | +| reexport/lib/index.js:1:1:2:0 | exports object of module index | +| reexport/lib/index.js:1:1:2:0 | module object of module index | | reexport/lib/src/utils/util.js:1:1:3:0 | exports object of module util | | reexport/lib/src/utils/util.js:1:1:3:0 | module object of module util | | refinements.js:1:1:8:1 | function f1 | @@ -341,8 +341,8 @@ | tst.js:174:1:183:1 | function awaitFlow | | tst.mjs:1:1:4:0 | exports object of module tst | | tst.mjs:1:1:4:0 | module object of module tst | -| tst.ts:1:1:15:0 | exports object of module tst | -| tst.ts:1:1:15:0 | module object of module tst | +| tst.ts:1:1:13:0 | exports object of module tst | +| tst.ts:1:1:13:0 | module object of module tst | | tst.ts:8:1:10:1 | function setX | | tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | function f | diff --git a/javascript/ql/test/library-tests/Flow/namespace-reexport.js b/javascript/ql/test/library-tests/Flow/namespace-reexport.js index 0a1e70c5abe..021a140061a 100644 --- a/javascript/ql/test/library-tests/Flow/namespace-reexport.js +++ b/javascript/ql/test/library-tests/Flow/namespace-reexport.js @@ -1,3 +1 @@ export * as h from './h'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/options b/javascript/ql/test/library-tests/Flow/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport-mixins.js b/javascript/ql/test/library-tests/Flow/reexport-mixins.js index f38cd783b9b..ff303ad3432 100644 --- a/javascript/ql/test/library-tests/Flow/reexport-mixins.js +++ b/javascript/ql/test/library-tests/Flow/reexport-mixins.js @@ -1,3 +1 @@ export default from './mixins'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js index 5ffc9d62bc4..e20cf1a083e 100644 --- a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js @@ -1,3 +1 @@ export data from './src/utils/util' - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/options b/javascript/ql/test/library-tests/Flow/reexport/lib/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/tst.ts b/javascript/ql/test/library-tests/Flow/tst.ts index 615efbb7103..63e329f75c0 100644 --- a/javascript/ql/test/library-tests/Flow/tst.ts +++ b/javascript/ql/test/library-tests/Flow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); let x2 = x; @@ -10,5 +10,3 @@ function setX() { } let a = A; - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/Functions/exprclosures.js b/javascript/ql/test/library-tests/Functions/exprclosures.js index 66e0f855744..dd6a10086bd 100644 --- a/javascript/ql/test/library-tests/Functions/exprclosures.js +++ b/javascript/ql/test/library-tests/Functions/exprclosures.js @@ -1,3 +1 @@ a.map(function(x) x+1); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Functions/options b/javascript/ql/test/library-tests/Functions/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Functions/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected index a54916e0142..414252881a2 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected @@ -1,4 +1,4 @@ -test_fromReference +test_getAReferenceTo | other_ns.js:2:11:2:12 | ns | NS | | other_ns.js:3:3:3:4 | ns | NS | | other_ns.js:3:3:3:8 | ns.foo | NS.foo | @@ -39,6 +39,7 @@ test_fromReference | test.js:12:19:12:25 | foo.bar | foo.bar | | test.js:13:7:13:15 | something | something | | test.js:14:5:14:23 | notUnique | bar.baz | +| test.js:14:5:14:23 | notUnique = bar.baz | bar.baz | | test.js:14:17:14:19 | bar | bar | | test.js:14:17:14:23 | bar.baz | bar.baz | | test.js:22:11:22:12 | ns | NS | @@ -54,10 +55,11 @@ test_fromReference | test.js:33:9:33:16 | bar = {} | foo.bar | | test.js:33:22:33:24 | foo | foo | | test.js:39:3:39:20 | lazyInit | foo.bar | +| test.js:39:3:39:20 | lazyInit = foo.bar | foo.bar | | test.js:39:14:39:16 | foo | foo | | test.js:39:14:39:20 | foo.bar | foo.bar | | test.js:40:3:40:10 | lazyInit | foo.bar | -test_fromRhs +test_getAnAssignmentTo | other_ns.js:4:9:4:16 | NS \|\| {} | NS | | other_ns.js:6:12:6:13 | {} | Conflict | | test.js:1:1:20:1 | functio ... ss {}\\n} | f | diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql index 4a233f3947b..8412511df8d 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql @@ -1,9 +1,11 @@ import javascript -query string test_fromReference(DataFlow::Node node) { - result = GlobalAccessPath::fromReference(node) +query string test_getAReferenceTo(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) } -query string test_fromRhs(DataFlow::Node node) { result = GlobalAccessPath::fromRhs(node) } +query string test_getAnAssignmentTo(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) +} -query string test_assignedUnique() { GlobalAccessPath::isAssignedInUniqueFile(result) } +query string test_assignedUnique() { AccessPath::isAssignedInUniqueFile(result) } diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html index 6cf4bfc564f..0b571650c40 100644 --- a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html +++ b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html @@ -1,4 +1,4 @@ -// semmle-extractor-options: --html all + (1) as child #0 diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/options b/javascript/ql/test/library-tests/HTML/HtmlText/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/HTML/HtmlText/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js index 8ba9bd12fee..1e4d7aed2e8 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js @@ -28,4 +28,4 @@ let source3 = "source3"; call2(source3, store); call2(source3, confounder); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js index 849516d57bb..9f1b0c9ba07 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js @@ -42,4 +42,4 @@ var o5 = {}; setP(o5, "not a source"); var sink10 = getP(o5); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/JSON/JSONError.expected b/javascript/ql/test/library-tests/JSON/JSONError.expected index 37d5aabfd08..e63d3862491 100644 --- a/javascript/ql/test/library-tests/JSON/JSONError.expected +++ b/javascript/ql/test/library-tests/JSON/JSONError.expected @@ -1,2 +1 @@ | invalid.json:3:1:3:1 | Error: Comments are not legal in JSON. | -| invalid.json:4:1:4:1 | Error: Comments are not legal in JSON. | diff --git a/javascript/ql/test/library-tests/JSON/invalid.json b/javascript/ql/test/library-tests/JSON/invalid.json index 54c870bb907..03f76948f63 100644 --- a/javascript/ql/test/library-tests/JSON/invalid.json +++ b/javascript/ql/test/library-tests/JSON/invalid.json @@ -1,4 +1,3 @@ "hi" // JSON doesn't have comments -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/JSON/options b/javascript/ql/test/library-tests/JSON/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/JSON/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Lines/Lines.expected b/javascript/ql/test/library-tests/Lines/Lines.expected index 552c1b8ff0e..e3c7973c9b8 100644 --- a/javascript/ql/test/library-tests/Lines/Lines.expected +++ b/javascript/ql/test/library-tests/Lines/Lines.expected @@ -1,4 +1,4 @@ -| tst1.js:1:1:1:55 | abc // semmle-extractor-options: --extract-program-text | abc // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:1:1:1:3 | abc | abc | \n | | tst1.js:2:1:2:3 | def | def | \r | | tst1.js:3:1:3:3 | ghi | ghi | \r\n | | tst1.js:4:1:4:3 | jkl | jkl | \n | @@ -6,13 +6,13 @@ | tst1.js:6:1:6:3 | mno | mno | \u2028 | | tst1.js:7:1:7:0 | | | \n | | tst1.js:8:1:8:3 | pqr | pqr | \u2029 | -| tst1.js:9:1:9:3 | stu | stu | | -| tst2.js:1:1:1:63 | first_line // semmle-extractor-options: --extract-program-text | first_line // semmle-extractor-options: --extract-program-text | \n | -| tst3.js:1:1:1:56 | 42; // semmle-extractor-options: --extract-program-text | 42; // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:9:1:9:3 | stu | stu | \n | +| tst2.js:1:1:1:10 | first_line | first_line | \n | +| tst3.js:1:1:1:3 | 42; | 42; | \n | | tst3.js:2:1:2:4 | \t42; | \t42; | \n | | tst3.js:3:1:3:5 | \t\t42; | \t\t42; | \n | | tst3.js:4:1:4:6 | \t\t\t42; | \t\t\t42; | \n | | tst3.js:5:1:5:6 | \t\t 42; | \t\t 42; | \n | | tst3.js:6:1:6:6 | \t \t42; | \t \t42; | \n | | tst3.js:7:1:7:7 | 42; | 42; | \n | -| tst3.js:8:1:8:5 | 42; | 42; | | +| tst3.js:8:1:8:5 | 42; | 42; | \n | diff --git a/javascript/ql/test/library-tests/Lines/options b/javascript/ql/test/library-tests/Lines/options new file mode 100644 index 00000000000..d51f2d49be2 --- /dev/null +++ b/javascript/ql/test/library-tests/Lines/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/Lines/tst1.js b/javascript/ql/test/library-tests/Lines/tst1.js index f10f44a7440..d5fa50c5f3a 100644 --- a/javascript/ql/test/library-tests/Lines/tst1.js +++ b/javascript/ql/test/library-tests/Lines/tst1.js @@ -1,5 +1,5 @@ -abc // semmle-extractor-options: --extract-program-text +abc def ghi jkl mnoโ€จ -pqrโ€ฉstu \ No newline at end of file +pqrโ€ฉstu diff --git a/javascript/ql/test/library-tests/Lines/tst2.js b/javascript/ql/test/library-tests/Lines/tst2.js index d3c77609145..c380edd400c 100644 --- a/javascript/ql/test/library-tests/Lines/tst2.js +++ b/javascript/ql/test/library-tests/Lines/tst2.js @@ -1 +1 @@ -first_line // semmle-extractor-options: --extract-program-text +first_line diff --git a/javascript/ql/test/library-tests/Lines/tst3.js b/javascript/ql/test/library-tests/Lines/tst3.js index ad0059d91ea..8c8468ffab2 100644 --- a/javascript/ql/test/library-tests/Lines/tst3.js +++ b/javascript/ql/test/library-tests/Lines/tst3.js @@ -1,8 +1,8 @@ -42; // semmle-extractor-options: --extract-program-text +42; 42; 42; 42; 42; 42; 42; - 42; \ No newline at end of file + 42; diff --git a/javascript/ql/test/library-tests/LocalObjects/options b/javascript/ql/test/library-tests/LocalObjects/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/LocalObjects/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/LocalObjects/tst.js b/javascript/ql/test/library-tests/LocalObjects/tst.js index dee138c0f27..a02a29776c0 100644 --- a/javascript/ql/test/library-tests/LocalObjects/tst.js +++ b/javascript/ql/test/library-tests/LocalObjects/tst.js @@ -89,5 +89,3 @@ let bound = {}; bound::unknown(); }); - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/b.js b/javascript/ql/test/library-tests/Modules/b.js index 4b58c09c31b..835bd1abbf6 100644 --- a/javascript/ql/test/library-tests/Modules/b.js +++ b/javascript/ql/test/library-tests/Modules/b.js @@ -5,5 +5,3 @@ f(); export { f as g }; export f2 from './a'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/c.js b/javascript/ql/test/library-tests/Modules/m/c.js index 6c3645f382d..8192ccc9b45 100644 --- a/javascript/ql/test/library-tests/Modules/m/c.js +++ b/javascript/ql/test/library-tests/Modules/m/c.js @@ -3,5 +3,3 @@ import * as b from '../b'; b.g(); export { g as h } from '../b'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/options b/javascript/ql/test/library-tests/Modules/m/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/m/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/options b/javascript/ql/test/library-tests/Modules/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/tests.expected b/javascript/ql/test/library-tests/Modules/tests.expected index 8cdd45f9066..39d24b09700 100644 --- a/javascript/ql/test/library-tests/Modules/tests.expected +++ b/javascript/ql/test/library-tests/Modules/tests.expected @@ -104,15 +104,15 @@ test_Module_exports | a.js:1:1:5:32 | | default | a.js:1:1:3:1 | export ... n 23;\\n} | | a.js:1:1:5:32 | | x | a.js:5:1:5:32 | export ... } = o; | | a.js:1:1:5:32 | | y | a.js:5:1:5:32 | export ... } = o; | -| b.js:1:1:10:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | -| b.js:1:1:10:0 | | g | b.js:5:1:5:18 | export { f as g }; | +| b.js:1:1:8:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | +| b.js:1:1:8:0 | | g | b.js:5:1:5:18 | export { f as g }; | | e.js:1:1:4:0 | | g | e.js:3:1:3:35 | export ... './a'; | | e.js:1:1:4:0 | | x | e.js:2:1:2:16 | export { x, y }; | | e.js:1:1:4:0 | | y | e.js:2:1:2:16 | export { x, y }; | | es2015_require.js:1:1:3:25 | | default | es2015_require.js:3:1:3:25 | export ... ss C {} | | export-in-mjs.mjs:1:1:1:34 | | exported_from_mjs | export-in-mjs.mjs:1:1:1:34 | export ... s = 42; | | f.ts:1:1:6:0 | | foo | f.ts:5:1:5:24 | export ... oo() {} | -| m/c.js:1:1:8:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | +| m/c.js:1:1:6:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | | tst.html:4:23:8:0 | | y | tst.html:7:3:7:22 | export const y = 42; | test_ExportDefaultDeclarations | a.js:1:1:3:1 | export ... n 23;\\n} | diff --git a/javascript/ql/test/library-tests/NPM/ImportedModule.expected b/javascript/ql/test/library-tests/NPM/ImportedModule.expected index 2a89dfeb394..ce2a65d591f 100644 --- a/javascript/ql/test/library-tests/NPM/ImportedModule.expected +++ b/javascript/ql/test/library-tests/NPM/ImportedModule.expected @@ -1,6 +1,6 @@ -| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:5:0 | | -| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:4:0 | | +| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | -| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | -| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:5:0 | | -| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | +| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:4:0 | | +| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/Modules.expected b/javascript/ql/test/library-tests/NPM/Modules.expected index 4d0dde9c33e..e7fa54d6f9a 100644 --- a/javascript/ql/test/library-tests/NPM/Modules.expected +++ b/javascript/ql/test/library-tests/NPM/Modules.expected @@ -1,9 +1,9 @@ | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | | test-package | src/lib/tst2.js:1:1:1:14 | | -| test-package | src/lib/tst.js:1:1:5:0 | | +| test-package | src/lib/tst.js:1:1:4:0 | | | test-package | src/tst2.js:1:1:1:13 | | | test-package | src/tst.js:1:1:2:38 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected index 67fd1880bf0..a8b7753abae 100644 --- a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected +++ b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected @@ -1,4 +1,4 @@ | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/src/index.js b/javascript/ql/test/library-tests/NPM/src/index.js index b875bfd3a10..e99778b633f 100644 --- a/javascript/ql/test/library-tests/NPM/src/index.js +++ b/javascript/ql/test/library-tests/NPM/src/index.js @@ -1,4 +1,3 @@ alert("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/lib/tst.js b/javascript/ql/test/library-tests/NPM/src/lib/tst.js index 840fb76057b..d8fc422959c 100644 --- a/javascript/ql/test/library-tests/NPM/src/lib/tst.js +++ b/javascript/ql/test/library-tests/NPM/src/lib/tst.js @@ -1,4 +1,3 @@ alert("world"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js index f53610fe05c..7dfe5aea1d2 100644 --- a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js @@ -1,4 +1,3 @@ ('alert' in this ? alert : console.log)("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected index 9f2e4dba88e..d1cc2576141 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected @@ -9,6 +9,7 @@ | b.js:1:1:8:0 | | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:7:15 | | d.js:1:1:1:38 | require ... s/ini') | | d.js:1:1:7:15 | | d.js:7:1:7:14 | require('foo') | +| e.js:1:1:6:0 | | e.js:5:1:5:18 | require("process") | | index.js:1:1:3:0 | | index.js:1:12:1:26 | require('path') | | index.js:1:1:3:0 | | index.js:2:1:2:41 | require ... b.js")) | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected index c038d8f9031..0fa0e65f359 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected @@ -1,6 +1,6 @@ | a.js:1:1:14:0 | | b.js:1:1:8:0 | | | a.js:1:1:14:0 | | d.js:1:1:7:15 | | -| a.js:1:1:14:0 | | e.js:1:1:7:0 | | +| a.js:1:1:14:0 | | e.js:1:1:6:0 | | | a.js:1:1:14:0 | | index.js:1:1:3:0 | | | a.js:1:1:14:0 | | sub/c.js:1:1:4:0 | | | b.js:1:1:8:0 | | sub/c.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NodeJS/Modules.expected b/javascript/ql/test/library-tests/NodeJS/Modules.expected index 05306ec82c5..1ef82d0328e 100644 --- a/javascript/ql/test/library-tests/NodeJS/Modules.expected +++ b/javascript/ql/test/library-tests/NodeJS/Modules.expected @@ -1,7 +1,7 @@ | a.js:1:1:14:0 | | a.js:0:0:0:0 | a.js | a.js | a | | b.js:1:1:8:0 | | b.js:0:0:0:0 | b.js | b.js | b | | d.js:1:1:7:15 | | d.js:0:0:0:0 | d.js | d.js | d | -| e.js:1:1:7:0 | | e.js:0:0:0:0 | e.js | e.js | e | +| e.js:1:1:6:0 | | e.js:0:0:0:0 | e.js | e.js | e | | index.js:1:1:3:0 | | index.js:0:0:0:0 | index.js | index.js | index | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:0:0:0:0 | mjs-files/require-from-js.js | mjs-files/require-from-js.js | require-from-js | | sub/c.js:1:1:4:0 | | sub/c.js:0:0:0:0 | sub/c.js | sub/c.js | c | diff --git a/javascript/ql/test/library-tests/NodeJS/Require.expected b/javascript/ql/test/library-tests/NodeJS/Require.expected index 491c80a9a87..7e9a50685ab 100644 --- a/javascript/ql/test/library-tests/NodeJS/Require.expected +++ b/javascript/ql/test/library-tests/NodeJS/Require.expected @@ -9,6 +9,7 @@ | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:1:38 | require ... s/ini') | | d.js:7:1:7:14 | require('foo') | +| e.js:5:1:5:18 | require("process") | | f.js:2:1:2:7 | r("fs") | | index.js:1:12:1:26 | require('path') | | index.js:2:1:2:41 | require ... b.js")) | diff --git a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected index a7ec65d67a2..e01527d2784 100644 --- a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected @@ -3,7 +3,7 @@ | a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | | | a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | | -| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:7:0 | | +| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | | | a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | | | b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | | diff --git a/javascript/ql/test/library-tests/NodeJS/e.js b/javascript/ql/test/library-tests/NodeJS/e.js index 0a3f338f7d0..22254c56326 100644 --- a/javascript/ql/test/library-tests/NodeJS/e.js +++ b/javascript/ql/test/library-tests/NodeJS/e.js @@ -2,5 +2,4 @@ require('./a.js'); })(); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/OptionalChaining/options b/javascript/ql/test/library-tests/OptionalChaining/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js index 97576676994..7367e64dd4c 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js +++ b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js @@ -13,4 +13,3 @@ DUMP(o3); DUMP(o4); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/tst.js b/javascript/ql/test/library-tests/OptionalChaining/tst.js index b0ee7435722..39389024d6d 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/OptionalChaining/tst.js @@ -13,5 +13,3 @@ a?.m().b; a.m?.().b; a.m()?.b; a?.m?.()?.b; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/PropWrite/tests.expected b/javascript/ql/test/library-tests/PropWrite/tests.expected index 33eff9b0628..beb4916f397 100644 --- a/javascript/ql/test/library-tests/PropWrite/tests.expected +++ b/javascript/ql/test/library-tests/PropWrite/tests.expected @@ -1,55 +1,55 @@ test_getAPropertyRead -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertyReference | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertySource | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | @@ -57,10 +57,10 @@ test_getAPropertySource | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:41:12:42 | {} | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | test_PropWritePropName | classes.ts:3:21:3:20 | constructor() {} | constructor | | classes.ts:4:3:4:24 | instanc ... foo(); | instanceField | @@ -70,123 +70,123 @@ test_PropWritePropName | classes.ts:12:17:12:37 | public ... erField | parameterField | | classes.ts:16:5:16:46 | constru ... {}) {} | constructor | | classes.ts:16:17:16:37 | public ... erField | parameterField | -| tst.js:3:5:3:8 | x: 4 | x | -| tst.js:4:5:6:5 | func: f ... ;\\n } | func | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | f | -| tst.js:12:9:12:8 | constructor() {} | constructor | -| tst.js:13:3:15:3 | static ... x);\\n } | func | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | f | -| tst.js:21:1:21:6 | C.prop | prop | -| tst.js:24:13:24:27 | onClick={click} | onClick | -| tst.js:27:3:27:26 | get x() ... null; } | x | -| tst.js:28:3:28:13 | set y(v) {} | y | -| tst.js:32:5:32:8 | n: 1 | n | +| tst.js:2:5:2:8 | x: 4 | x | +| tst.js:3:5:5:5 | func: f ... ;\\n } | func | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | f | +| tst.js:11:9:11:8 | constructor() {} | constructor | +| tst.js:12:3:14:3 | static ... x);\\n } | func | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | f | +| tst.js:20:1:20:6 | C.prop | prop | +| tst.js:23:13:23:27 | onClick={click} | onClick | +| tst.js:26:3:26:26 | get x() ... null; } | x | +| tst.js:27:3:27:13 | set y(v) {} | y | +| tst.js:31:5:31:8 | n: 1 | n | test_getAPropertyRead2 -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_getAPropertyReference2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_hasPropertyWrite | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:24:12:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:8:3:8 | 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:8:32:8 | 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:8:2:8 | 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:8:31:8 | 1 | test_PropWriteBase | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:3:21:3:20 | this | | classes.ts:8:15:8:35 | public ... erField | classes.ts:8:3:8:2 | this | | classes.ts:12:17:12:37 | public ... erField | classes.ts:12:5:12:4 | this | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:5:16:4 | this | -| tst.js:3:5:3:8 | x: 4 | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:12:1:19:1 | class C ... ;\\n }\\n} | -| tst.js:21:1:21:6 | C.prop | tst.js:21:1:21:1 | C | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:8:24:57 |
    | -| tst.js:27:3:27:26 | get x() ... null; } | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:28:3:28:13 | set y(v) {} | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:32:5:32:8 | n: 1 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:18:38:20 | "b" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:23:38:25 | "c" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:39:13:39:15 | "a" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:40:15:40:17 | "b" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:40:20:40:22 | "c" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:41:18:41:20 | "b" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:42:13:42:15 | "a" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:27:42:29 | "d" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | +| tst.js:2:5:2:8 | x: 4 | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:11:1:18:1 | class C ... ;\\n }\\n} | +| tst.js:20:1:20:6 | C.prop | tst.js:20:1:20:1 | C | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:8:23:57 |
    | +| tst.js:26:3:26:26 | get x() ... null; } | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:27:3:27:13 | set y(v) {} | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:31:5:31:8 | n: 1 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:37:13:37:15 | "a" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:18:37:20 | "b" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:23:37:25 | "c" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:38:20:38:22 | "c" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:39:15:39:17 | "b" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:40:13:40:15 | "a" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:40:18:40:20 | "b" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:27:41:29 | "d" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | test_getAPropertyWrite | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | test_PropWrite | classes.ts:3:21:3:20 | constructor() {} | | classes.ts:4:3:4:24 | instanc ... foo(); | @@ -196,46 +196,46 @@ test_PropWrite | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | -| tst.js:3:5:3:8 | x: 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | -| tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | -| tst.js:24:13:24:27 | onClick={click} | -| tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:28:3:28:13 | set y(v) {} | -| tst.js:32:5:32:8 | n: 1 | -| tst.js:33:5:33:10 | [v]: 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | +| tst.js:2:5:2:8 | x: 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | +| tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | +| tst.js:23:13:23:27 | onClick={click} | +| tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:27:3:27:13 | set y(v) {} | +| tst.js:31:5:31:8 | n: 1 | +| tst.js:32:5:32:10 | [v]: 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | test_getAPropertyWrite2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | test_PropWriteRhs | classes.ts:3:21:3:20 | constructor() {} | classes.ts:3:21:3:20 | () {} | | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:4:19:4:23 | foo() | @@ -246,27 +246,27 @@ test_PropWriteRhs | classes.ts:16:5:16:46 | constru ... {}) {} | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:41:16:42 | {} | -| tst.js:3:5:3:8 | x: 4 | tst.js:3:8:3:8 | 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | tst.js:12:9:12:8 | () {} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | tst.js:16:4:18:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:22:24:26 | click | -| tst.js:32:5:32:8 | n: 1 | tst.js:32:8:32:8 | 1 | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:33:10:33:10 | 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:34:14:34:14 | 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:35:20:35:20 | 4 | +| tst.js:2:5:2:8 | x: 4 | tst.js:2:8:2:8 | 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | tst.js:11:9:11:8 | () {} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | tst.js:15:4:17:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:22:23:26 | click | +| tst.js:31:5:31:8 | n: 1 | tst.js:31:8:31:8 | 1 | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:32:10:32:10 | 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:33:14:33:14 | 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:34:20:34:20 | 4 | +| tst.js:37:13:37:15 | "a" | tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | tst.js:41:27:41:29 | "d" | diff --git a/javascript/ql/test/library-tests/PropWrite/tst.js b/javascript/ql/test/library-tests/PropWrite/tst.js index 8b2ad5aa3e2..99e9d5ffb1c 100644 --- a/javascript/ql/test/library-tests/PropWrite/tst.js +++ b/javascript/ql/test/library-tests/PropWrite/tst.js @@ -1,4 +1,3 @@ -// semmle-extractor-options: --experimental var obj = { x: 4, func: function() { diff --git a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js index cbff84ef9b4..faa017a8bd3 100644 --- a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js +++ b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js @@ -1,4 +1,2 @@ var q = { ...o, x: 42, ...p }; let { x, ...r } = q, { z } = {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected index c58a7c511d1..010375e1ab8 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected @@ -44,14 +44,11 @@ | tst.js:236:9:236:24 | isWhitelisted(v) | ExampleConfiguration | true | tst.js:236:23:236:23 | v | | tst.js:240:9:240:28 | config.allowValue(v) | ExampleConfiguration | true | tst.js:240:27:240:27 | v | | tst.js:252:16:252:36 | whiteli ... ains(x) | ExampleConfiguration | true | tst.js:252:35:252:35 | x | -| tst.js:254:9:254:12 | f(v) | ExampleConfiguration | true | tst.js:254:11:254:11 | v | | tst.js:261:25:261:45 | whiteli ... ains(y) | ExampleConfiguration | true | tst.js:261:44:261:44 | y | -| tst.js:264:9:264:12 | g(v) | ExampleConfiguration | true | tst.js:264:11:264:11 | v | | tst.js:271:25:271:45 | whiteli ... ains(z) | ExampleConfiguration | true | tst.js:271:44:271:44 | z | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:16:281:17 | x2 | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:22:281:25 | null | | tst.js:281:30:281:51 | whiteli ... ins(x2) | ExampleConfiguration | true | tst.js:281:49:281:50 | x2 | -| tst.js:283:9:283:13 | f2(v) | ExampleConfiguration | true | tst.js:283:12:283:12 | v | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:16:290:17 | x3 | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:22:290:25 | null | | tst.js:290:30:290:51 | whiteli ... ins(x3) | ExampleConfiguration | true | tst.js:290:49:290:50 | x3 | @@ -61,7 +58,6 @@ | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:25:327:26 | x7 | | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:31:327:34 | null | | tst.js:327:39:327:60 | whiteli ... ins(x7) | ExampleConfiguration | true | tst.js:327:58:327:59 | x7 | -| tst.js:330:9:330:13 | f7(v) | ExampleConfiguration | true | tst.js:330:12:330:12 | v | | tst.js:337:25:337:46 | whiteli ... ins(x8) | ExampleConfiguration | true | tst.js:337:44:337:45 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:16:338:17 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:22:338:25 | null | @@ -70,6 +66,5 @@ | tst.js:356:16:356:27 | x10 !== null | ExampleConfiguration | false | tst.js:356:24:356:27 | null | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:32:356:34 | x10 | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:40:356:48 | undefined | -| tst.js:358:9:358:14 | f10(v) | ExampleConfiguration | false | tst.js:358:13:358:13 | v | | tst.js:370:9:370:29 | o.p == ... listed" | ExampleConfiguration | true | tst.js:370:9:370:11 | o.p | | tst.js:377:11:377:32 | o[p] == ... listed" | ExampleConfiguration | true | tst.js:377:11:377:14 | o[p] | diff --git a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected index 050f80bc071..54b35166b15 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected @@ -53,7 +53,6 @@ | tst.js:333:14:333:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:341:14:341:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:343:14:343:14 | v | tst.js:248:13:248:20 | SOURCE() | -| tst.js:350:14:350:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:352:14:352:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:359:14:359:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:368:10:368:12 | o.p | tst.js:367:13:367:20 | SOURCE() | diff --git a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected index 50804043f95..f650c93185c 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected @@ -37,6 +37,7 @@ | tst.js:265:14:265:14 | v | ExampleConfiguration | | tst.js:284:14:284:14 | v | ExampleConfiguration | | tst.js:331:14:331:14 | v | ExampleConfiguration | +| tst.js:350:14:350:14 | v | ExampleConfiguration | | tst.js:356:16:356:27 | x10 | ExampleConfiguration | | tst.js:356:32:356:34 | x10 | ExampleConfiguration | | tst.js:361:14:361:14 | v | ExampleConfiguration | diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js index 78986d6af37..a7a05590540 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/tst.js +++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js @@ -347,7 +347,7 @@ function IndirectSanitizer () { return unknown() && whitelist.contains(x9) && unknown(); } if (f9(v)) { - SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED + SINK(v); } else { SINK(v); } diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 2722f67d6fd..93dc5e6e200 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,10 +69,14 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | | spread.js:2:15:2:22 | source() | spread.js:4:8:4:19 | { ...taint } | | spread.js:2:15:2:22 | source() | spread.js:5:8:5:43 | { f: 'h ... orld' } | | spread.js:2:15:2:22 | source() | spread.js:7:8:7:19 | [ ...taint ] | diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql index 0b1d5d9da84..26c66a1b4fe 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql @@ -1,7 +1,11 @@ import javascript import semmle.javascript.dataflow.InferredTypes -DataFlow::CallNode getACall(string name) { result.getCalleeName() = name } +DataFlow::CallNode getACall(string name) { + result.getCalleeName() = name + or + result.getCalleeNode().getALocalSource() = DataFlow::globalVarRef(name) +} class Sink extends DataFlow::Node { Sink() { this = getACall("sink").getAnArgument() } diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index 6a589e3e0d9..f2799d763fd 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -41,10 +41,18 @@ | partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:41:10:41:18 | id(taint) | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:51:14:51:14 | x | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:17:14:17:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:21:14:21:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:25:14:25:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:52:10:52:10 | x | | thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field | | thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 | | tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x | diff --git a/javascript/ql/test/library-tests/TaintTracking/exceptions.js b/javascript/ql/test/library-tests/TaintTracking/exceptions.js index b8946b5603a..98e3e7ce009 100644 --- a/javascript/ql/test/library-tests/TaintTracking/exceptions.js +++ b/javascript/ql/test/library-tests/TaintTracking/exceptions.js @@ -169,5 +169,3 @@ function throwThoughLibrary(xs) { sink(e); // OK - doesn't catch exception from event listener } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index cd5351720ba..9714d258df5 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -11,4 +11,4 @@ function closure() { let resolver = Promise.withResolver(); resolver.resolve(source()); sink(resolver.promise); // NOT OK -} +} \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js new file mode 100644 index 00000000000..6df74cf29ee --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js @@ -0,0 +1,35 @@ +function test() { + function myCheck1(x) { + return x === "a" && something() && somethingElse(); + } + function myCheck2(x) { + return something() && x === "a" && somethingElse(); + } + function myCheck3(x) { + return something() && somethingElse() && x === "a"; + } + + let taint = source(); + + sink(taint); // NOT OK + + if (myCheck1(taint)) { + sink(taint); // OK + } + + if (myCheck2(taint)) { + sink(taint); // OK + } + + if (myCheck3(taint)) { + sink(taint); // OK + } + + function badCheck(x) { + return something && x + isSafe(x) != null; + } + + if (badCheck(taint)) { + sink(taint); // NOT OK + } +} diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js index 494e828460d..03d6a9aedd7 100644 --- a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js @@ -38,3 +38,17 @@ class C { }); } } + +function reflective() { + let x = source(); + + sink(x); // NOT OK + + if (isSafe.call(x)) { + sink(x); // NOT OK - `isSafe` does not sanitize the receiver + } + + if (isSafe.call(null, x)) { + sink(x); // OK + } +} diff --git a/javascript/ql/test/library-tests/Templates/templates-revised.js b/javascript/ql/test/library-tests/Templates/templates-revised.js index 0ca81631fb4..7df488e53f9 100644 --- a/javascript/ql/test/library-tests/Templates/templates-revised.js +++ b/javascript/ql/test/library-tests/Templates/templates-revised.js @@ -1,3 +1 @@ tag `\unvalid escape sequence`; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/options b/javascript/ql/test/library-tests/ThisExpr/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/ThisExpr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/tst.js b/javascript/ql/test/library-tests/ThisExpr/tst.js index 418021624e7..316e3feb1de 100644 --- a/javascript/ql/test/library-tests/ThisExpr/tst.js +++ b/javascript/ql/test/library-tests/ThisExpr/tst.js @@ -146,4 +146,3 @@ class C_lodash { } } -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js index 434f0d0ae61..2257a74aa2a 100644 --- a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js +++ b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js @@ -31,5 +31,3 @@ new h2(23, 42,); x => x; function f4(x = 42,) {} - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js index 6c3458781a1..28d7e45c44e 100644 --- a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js @@ -21,4 +21,3 @@ v7 = x ?? {}; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js index 4890c8335cc..42747617b6b 100644 --- a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js @@ -22,4 +22,3 @@ var v11 = h(); var v12 = h?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/options b/javascript/ql/test/library-tests/TypeScript/Modifiers/options new file mode 100644 index 00000000000..d51f2d49be2 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts index a56c724cf57..615a36ae6e5 100644 --- a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts @@ -113,5 +113,3 @@ interface InterfaceFields { z?: number; readonly w?: number; } - -// semmle-extractor-options: --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts index 6bba445dce4..55716a17a65 100644 --- a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts @@ -23,5 +23,3 @@ var nns: Array; var dns: Array; var anys: Array<*>; var vars: Array<...number>; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/YAMLError.expected b/javascript/ql/test/library-tests/YAML/YAMLError.expected index 2045e49be51..386d8874ef2 100644 --- a/javascript/ql/test/library-tests/YAML/YAMLError.expected +++ b/javascript/ql/test/library-tests/YAML/YAMLError.expected @@ -1 +1 @@ -| err.yaml:4:1:4:1 | found unexpected end of stream | +| err.yaml:3:1:3:1 | found unexpected end of stream | diff --git a/javascript/ql/test/library-tests/YAML/err.yaml b/javascript/ql/test/library-tests/YAML/err.yaml index f6d3951be96..96d2d75ddc0 100644 --- a/javascript/ql/test/library-tests/YAML/err.yaml +++ b/javascript/ql/test/library-tests/YAML/err.yaml @@ -1,3 +1,2 @@ "unterminated string -# semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/options b/javascript/ql/test/library-tests/YAML/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/YAML/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html index 23449e03c0e..29608f2da53 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html @@ -17,4 +17,3 @@
    -// semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html index 9678f75e0cc..87bb928ac4c 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html @@ -7,4 +7,3 @@
    {{myExpr3}}
    -semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options new file mode 100644 index 00000000000..46bf0192945 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/Express/options b/javascript/ql/test/library-tests/frameworks/Express/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Express/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/options b/javascript/ql/test/library-tests/frameworks/ReactJS/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js index df115aac5b8..697bc35c150 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js @@ -11,5 +11,3 @@ class Reads extends React.Component { prevState.p4; } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js index 4f15d9a1b31..692400c7381 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js @@ -43,5 +43,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js index accf4713d71..39a340ccf83 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js +++ b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js @@ -10,5 +10,3 @@ async () => { // ... error checks } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/stmts/conditionals.js b/javascript/ql/test/library-tests/stmts/conditionals.js index 12562b2881f..e21a4299f87 100644 --- a/javascript/ql/test/library-tests/stmts/conditionals.js +++ b/javascript/ql/test/library-tests/stmts/conditionals.js @@ -1,4 +1,4 @@ -if (true) // semmle-extractor-options: --extract-program-text +if (true) ; if (b) ; diff --git a/javascript/ql/test/library-tests/stmts/es2015.js b/javascript/ql/test/library-tests/stmts/es2015.js index 6264c54a04f..09a501be36b 100644 --- a/javascript/ql/test/library-tests/stmts/es2015.js +++ b/javascript/ql/test/library-tests/stmts/es2015.js @@ -1,2 +1,2 @@ -for (var x of [1, 2, 3]) // semmle-extractor-options: --extract-program-text +for (var x of [1, 2, 3]) console.log(x); diff --git a/javascript/ql/test/library-tests/stmts/foreach.js b/javascript/ql/test/library-tests/stmts/foreach.js index ee6fd60e59b..1df30053437 100644 --- a/javascript/ql/test/library-tests/stmts/foreach.js +++ b/javascript/ql/test/library-tests/stmts/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/functions.js b/javascript/ql/test/library-tests/stmts/functions.js index f1ac615a040..20ecacefad5 100644 --- a/javascript/ql/test/library-tests/stmts/functions.js +++ b/javascript/ql/test/library-tests/stmts/functions.js @@ -1,4 +1,4 @@ -function g(x, y) { // semmle-extractor-options: --extract-program-text +function g(x, y) { return x+y; } diff --git a/javascript/ql/test/library-tests/stmts/guardedCatch.js b/javascript/ql/test/library-tests/stmts/guardedCatch.js index 2c9a24cdb07..0c7b4c2b890 100644 --- a/javascript/ql/test/library-tests/stmts/guardedCatch.js +++ b/javascript/ql/test/library-tests/stmts/guardedCatch.js @@ -7,5 +7,3 @@ function f(g) { console.log("something else!"); } } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/jscript.js b/javascript/ql/test/library-tests/stmts/jscript.js index 6e281fcec08..0f6a81c8fb3 100644 --- a/javascript/ql/test/library-tests/stmts/jscript.js +++ b/javascript/ql/test/library-tests/stmts/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/legacyletstmt.js b/javascript/ql/test/library-tests/stmts/legacyletstmt.js index e88411c12c1..89b5e7505e9 100644 --- a/javascript/ql/test/library-tests/stmts/legacyletstmt.js +++ b/javascript/ql/test/library-tests/stmts/legacyletstmt.js @@ -1,5 +1,3 @@ let (x = 23, y = 19) { console.log(x + y); } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/loops.js b/javascript/ql/test/library-tests/stmts/loops.js index e2a63b3e3f9..6d424254d74 100644 --- a/javascript/ql/test/library-tests/stmts/loops.js +++ b/javascript/ql/test/library-tests/stmts/loops.js @@ -1,4 +1,4 @@ -while(true) // semmle-extractor-options: --extract-program-text +while(true) ; outer: for(a; b; c) { for(;;) diff --git a/javascript/ql/test/library-tests/stmts/options b/javascript/ql/test/library-tests/stmts/options new file mode 100644 index 00000000000..7b186f72cc5 --- /dev/null +++ b/javascript/ql/test/library-tests/stmts/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/others.js b/javascript/ql/test/library-tests/stmts/others.js index 58d6c5c1709..3b2a62a47bf 100644 --- a/javascript/ql/test/library-tests/stmts/others.js +++ b/javascript/ql/test/library-tests/stmts/others.js @@ -1,4 +1,4 @@ -with(a) { // semmle-extractor-options: --extract-program-text +with(a) { } debugger; var x = 23, y; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/tests.expected b/javascript/ql/test/library-tests/stmts/tests.expected index c4632fbc065..75d6f0a24b4 100644 --- a/javascript/ql/test/library-tests/stmts/tests.expected +++ b/javascript/ql/test/library-tests/stmts/tests.expected @@ -4,14 +4,11 @@ test_LetStmt test_LineTerminators | conditionals.js:12:1:12:1 | } | | functions.js:9:1:9:1 | } | -| guardedCatch.js:11:1:11:65 | //semmle-extractor-options: --experimental --extract-program-text | -| jscript.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | -| legacyletstmt.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | | loops.js:22:1:22:18 | for (x = 0 in xs); | | others.js:4:1:4:14 | var x = 23, y; | | try.js:5:1:5:29 | try {} catch(x) {} finally {} | test_EnclosingStmt -| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (tru ... t\\n ; | +| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (true)\\n ; | | conditionals.js:3:5:3:5 | b | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | | conditionals.js:7:9:7:9 | b | conditionals.js:7:1:12:1 | switch ... ault:\\n} | | conditionals.js:8:6:8:7 | 23 | conditionals.js:8:1:8:8 | case 23: | @@ -96,7 +93,7 @@ test_EnclosingStmt | legacyletstmt.js:2:15:2:15 | x | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:15:2:19 | x + y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:19:2:19 | y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | -| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(t ... t\\n ; | +| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(true)\\n ; | | loops.js:3:1:3:5 | outer | loops.js:3:1:11:1 | outer: ... inue;\\n} | | loops.js:3:12:3:12 | a | loops.js:3:8:11:1 | for(a; ... inue;\\n} | | loops.js:3:15:3:15 | b | loops.js:3:8:11:1 | for(a; ... inue;\\n} | @@ -129,7 +126,7 @@ test_EnclosingStmt | loops.js:22:6:22:6 | x | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:10:22:10 | 0 | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:15:22:16 | xs | loops.js:22:1:22:18 | for (x = 0 in xs); | -| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) ... -text\\n} | +| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) {\\n} | | others.js:4:5:4:5 | x | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:5:4:10 | x = 23 | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:9:4:10 | 23 | others.js:4:1:4:14 | var x = 23, y; | @@ -140,7 +137,7 @@ test_EnclosingStmt | try.js:5:14:5:14 | x | try.js:5:8:5:18 | catch(x) {} | test_NumCatchClauses | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | 2 | -| try.js:1:1:3:16 | try { / ... ) { ; } | 1 | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | 1 | | try.js:4:1:4:20 | try {} finally { ; } | 0 | | try.js:5:1:5:29 | try {} ... ally {} | 1 | test_DoubleColonMethods @@ -151,7 +148,7 @@ test_SemicolonInsertion test_getGuard | guardedCatch.js:4:4:6:2 | catch ( ... !");\\n\\t} | guardedCatch.js:4:16:4:33 | e instanceof Error | test_Containers -| conditionals.js:1:1:2:5 | if (tru ... t\\n ; | conditionals.js:1:1:12:1 | | +| conditionals.js:1:1:2:5 | if (true)\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:2:5:2:5 | ; | conditionals.js:1:1:12:1 | | | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:4:5:4:5 | ; | conditionals.js:1:1:12:1 | | @@ -164,22 +161,22 @@ test_Containers | es2015.js:1:1:2:16 | for (va ... log(x); | es2015.js:1:1:3:0 | | | es2015.js:1:6:1:10 | var x | es2015.js:1:1:3:0 | | | es2015.js:2:2:2:16 | console.log(x); | es2015.js:1:1:3:0 | | -| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:11:0 | | -| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:11:0 | | -| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:4:11:4:18 | var item | foreach.js:1:1:11:0 | | -| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:11:0 | | -| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:11:0 | | +| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:9:0 | | +| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:9:0 | | +| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:4:11:4:18 | var item | foreach.js:1:1:9:0 | | +| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:9:0 | | +| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:9:0 | | | functions.js:1:1:3:1 | functio ... x+y;\\n} | functions.js:1:1:9:1 | | -| functions.js:1:18:3:1 | { // se ... x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | +| functions.js:1:18:3:1 | {\\n return x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:2:5:2:15 | return x+y; | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:5:1:5:15 | function h() {} | functions.js:1:1:9:1 | | | functions.js:5:14:5:15 | {} | functions.js:5:1:5:15 | function h() {} | | functions.js:7:1:9:1 | k = fun ... turn;\\n} | functions.js:1:1:9:1 | | | functions.js:7:16:9:1 | {\\n return;\\n} | functions.js:7:5:9:1 | functio ... turn;\\n} | | functions.js:8:5:8:11 | return; | functions.js:7:5:9:1 | functio ... turn;\\n} | -| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:11:65 | | +| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:10:0 | | | guardedCatch.js:1:15:9:1 | {\\n\\ttry ... );\\n\\t}\\n} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:6:4:2 | {\\n\\t\\tg();\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | @@ -190,14 +187,14 @@ test_Containers | guardedCatch.js:6:4:8:2 | catch ( ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:6:14:8:2 | {\\n\\t\\tcon ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:7:3:7:33 | console ... lse!"); | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | -| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:1:27:1:28 | {} | jscript.js:1:1:1:28 | functio ... ad() {} | -| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:3:35:3:36 | {} | jscript.js:3:17:3:36 | function onload() {} | -| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:5:65 | | -| loops.js:1:1:2:5 | while(t ... t\\n ; | loops.js:1:1:22:18 | | +| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:4:0 | | +| loops.js:1:1:2:5 | while(true)\\n ; | loops.js:1:1:22:18 | | | loops.js:2:5:2:5 | ; | loops.js:1:1:22:18 | | | loops.js:3:1:11:1 | outer: ... inue;\\n} | loops.js:1:1:22:18 | | | loops.js:3:8:11:1 | for(a; ... inue;\\n} | loops.js:1:1:22:18 | | @@ -223,12 +220,12 @@ test_Containers | loops.js:21:16:21:16 | ; | loops.js:1:1:22:18 | | | loops.js:22:1:22:18 | for (x = 0 in xs); | loops.js:1:1:22:18 | | | loops.js:22:18:22:18 | ; | loops.js:1:1:22:18 | | -| others.js:1:1:2:1 | with(a) ... -text\\n} | others.js:1:1:4:14 | | -| others.js:1:9:2:1 | { // se ... -text\\n} | others.js:1:1:4:14 | | +| others.js:1:1:2:1 | with(a) {\\n} | others.js:1:1:4:14 | | +| others.js:1:9:2:1 | {\\n} | others.js:1:1:4:14 | | | others.js:3:1:3:9 | debugger; | others.js:1:1:4:14 | | | others.js:4:1:4:14 | var x = 23, y; | others.js:1:1:4:14 | | -| try.js:1:1:3:16 | try { / ... ) { ; } | try.js:1:1:5:29 | | -| try.js:1:5:3:1 | { // se ... "!";\\n} | try.js:1:1:5:29 | | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | try.js:1:1:5:29 | | +| try.js:1:5:3:1 | {\\n throw "!";\\n} | try.js:1:1:5:29 | | | try.js:2:5:2:14 | throw "!"; | try.js:1:1:5:29 | | | try.js:3:3:3:16 | catch(x) { ; } | try.js:1:1:5:29 | | | try.js:3:12:3:16 | { ; } | try.js:1:1:5:29 | | diff --git a/javascript/ql/test/library-tests/stmts/try.js b/javascript/ql/test/library-tests/stmts/try.js index 2d82952fbd3..0151114bf84 100644 --- a/javascript/ql/test/library-tests/stmts/try.js +++ b/javascript/ql/test/library-tests/stmts/try.js @@ -1,4 +1,4 @@ -try { // semmle-extractor-options: --extract-program-text +try { throw "!"; } catch(x) { ; } try {} finally { ; } diff --git a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected index 158f001459c..bf97e07b559 100644 --- a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected +++ b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected @@ -24,7 +24,7 @@ | x | defaultargs.js:3:3:3:25 | functio ... = x) {} | | x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | | x | for.js:1:2:5:1 | functio ... x;\\n} | -| x | legacyletstmt.js:1:1:9:42 | | +| x | legacyletstmt.js:1:1:8:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | @@ -36,7 +36,7 @@ | x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | | y | defaultargs.js:3:3:3:25 | functio ... = x) {} | | y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| y | legacyletstmt.js:1:1:9:42 | | +| y | legacyletstmt.js:1:1:8:0 | | | y | let.js:1:1:22:0 | | | y | let.js:14:1:21:1 | functio ... }\\n} | | y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | diff --git a/javascript/ql/test/library-tests/variables/legacyletstmt.js b/javascript/ql/test/library-tests/variables/legacyletstmt.js index 07531d1cc9c..69beaac8a09 100644 --- a/javascript/ql/test/library-tests/variables/legacyletstmt.js +++ b/javascript/ql/test/library-tests/variables/legacyletstmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/variables/options b/javascript/ql/test/library-tests/variables/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/library-tests/variables/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html index 3277461d787..98a490ec408 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html @@ -4,5 +4,4 @@
  • First element
  • Second element -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html index 7800cfcd048..bb5969c1f79 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html @@ -10,5 +10,4 @@
  • duplicate-class
  • duplicate-class
  • -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html index 370337bc7af..92af95c3e3c 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html index 9b6a94b0e2d..dfe1141a21b 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html index eedc176211b..a78e3314283 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html index 9b6a94b0e2d..dfe1141a21b 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html index 666592a7716..9da8fcde502 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html index 9a7815efb64..1dfea0491fe 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/options b/javascript/ql/test/query-tests/DOM/HTML/options new file mode 100644 index 00000000000..49be7a9261e --- /dev/null +++ b/javascript/ql/test/query-tests/DOM/HTML/options @@ -0,0 +1 @@ +semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js index f91c316b0ed..7824a7ffe02 100644 --- a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js +++ b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js @@ -1,3 +1,3 @@ var arguments; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js index d3594220a05..6e79be49a81 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js @@ -38,4 +38,4 @@ function Worker(opt_arg0) {} */ Worker.prototype.onmessage = function() {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js index 6b5cc4cc2d8..22e649c68c6 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js @@ -3,5 +3,3 @@ var x = 42; class C { myX = x } - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js index a32e349e56d..11caae4e1b1 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js @@ -40,4 +40,4 @@ function Element() {} */ Element.prototype.clientTop; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js index 19dd15789e9..0a9eab06996 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js @@ -2,4 +2,4 @@ var f = function() {}; var f = function(x) {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js index ffab5c80539..44cf825c3cd 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js @@ -1,4 +1,2 @@ var f = ({...p}) => {}; var g = ({...p}) => {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js index a3c8c8999c0..4327b4885f5 100644 --- a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js +++ b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js @@ -1,4 +1,4 @@ // OK: overly long parameter lists in external APIs aren't the fault of the externs definitions function f(a, b, c, d, e, f, g, h) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js index 2d543e5bf1b..470b14e8300 100644 --- a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js @@ -12,5 +12,3 @@ this.addPropertyListener(prop.name, function(_, _, _, a) { function f(x, y, x) { 'use strict'; } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js index ec8e5c4f6db..9153844b527 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js @@ -1,3 +1,3 @@ function String(str) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js index 2a7d8c0b4e5..43b3b2ebfb2 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js @@ -1,5 +1,3 @@ function f({ x, ...ys }) { return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js index b3210a08775..ce0a9ddfd0f 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js @@ -2,5 +2,3 @@ function test(bar, e) { let foo = bar; e.target::foo::baz(); } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/options b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js index d4e6de4b3ba..3f0516d2266 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js @@ -2,5 +2,3 @@ function f(o) { let { x, ...ys } = o; return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js index d3fff886259..98a1d68e520 100644 --- a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js +++ b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js @@ -53,4 +53,4 @@ function Error() {} */ function SyntaxError() {} -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js index 46199104674..f500d4cdafc 100644 --- a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js @@ -232,5 +232,3 @@ function l() { function f(...x) { x === 42 }; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js index e1ef6f1cdfd..a454ed9bde3 100644 --- a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js @@ -107,4 +107,3 @@ function l() { g(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js index 70685e250c1..58b2c99e892 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js @@ -36,4 +36,4 @@ function Element() {} Element.prototype.innerHTML; -// semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js index 0329cdf038d..03bfc0b5573 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js @@ -11,5 +11,3 @@ class C extends Q { this.arg = this.arg; // NOT OK } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js index 356d0cf57ee..a8cedd993b2 100644 --- a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js @@ -1,4 +1,2 @@ var n = 1<<40; // NOT OK var n2 = BigInt(1) << 40n; // OK - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js index 23651d79e6c..01a0c35bc5b 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js @@ -3,5 +3,3 @@ class A { } class B {} - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js index 2df3535216a..9be73a4dde5 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js @@ -7,4 +7,3 @@ b(); b?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js index 9f662507227..fa6003ad795 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js @@ -7,4 +7,3 @@ b.p; b?.p; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js index ae0bcba2a23..c0cd2619e81 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js @@ -4,5 +4,3 @@ function outer() { } inner().next() } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js index 6733344c3ba..6657556b072 100644 --- a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js @@ -172,5 +172,3 @@ class Component4 extends React.Component { this.setState({ }); } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js index f27d6054e27..433db5a26f4 100644 --- a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js +++ b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js @@ -3,4 +3,4 @@ */ function f(x) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js index 0095642669c..1df30053437 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js index 373939cae64..0f6a81c8fb3 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js index 51e8fd38fda..a5c7a09b6be 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js @@ -3,5 +3,3 @@ var x = 42, y = 19; console.log(let (x = 23, y = 19) x + y); console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js index 07531d1cc9c..69beaac8a09 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js index bb08a86ceec..3cca1b5c615 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js @@ -2,5 +2,3 @@ var numbers = [1, 2, 3, 4, 5]; var squares = [i*i for (i of numbers)]; var specialKeyCodes = [for (keyCodeName of Object.keys(SPECIAL_CODES_MAP)) SPECIAL_CODES_MAP[keyCodeName]]; - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js index dbfeda687e0..202ea2a262a 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js @@ -6,5 +6,3 @@ // OK [1, 2, 3].map((x) => x * x); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js index 30135633974..08542e2be52 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js @@ -1,4 +1,2 @@ var a = [23,,42]; var desc = [for(i in a) i + " = a[" + i + "]"]; - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js index 6a489653379..3ed85a70934 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js @@ -60,5 +60,3 @@ function invoke(fn) { } invoke(C); invoke(function() {}); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js index c81b555e5aa..0ffbf63dd3f 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js @@ -7,4 +7,4 @@ String.prototype.toString = function() {}; function Array() {} Array.prototype.toString = function() {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected index 81808eb76ba..bab6488e83b 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected @@ -1,4 +1,4 @@ | export.js:5:8:5:17 | var x = 42 | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | export.js:1:1:29:0 | | the enclosing script | -| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:27:42 | | the enclosing script | +| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:26:0 | | the enclosing script | | tst.js:5:1:5:3 | var a = ... : 2\\n } | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | | tst.js:7:3:7:10 | return 1 | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js index 66a296a0ae8..5e9b07cf675 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js @@ -23,5 +23,3 @@ foo(); foo(); foo(); foo(); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js index cf8665ea531..c8a88126efb 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js @@ -39,4 +39,4 @@ function Number() {} Number.parseFloat = function(num) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js index 2da4e693aeb..e7aaa89f128 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js @@ -1,4 +1,2 @@ function findBox() { return $("box.important - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js index 5081e9991d1..a68f3ad35f9 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js @@ -4,6 +4,3 @@ function idMaker(){ // NOT OK yield index++; } - -//semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected index e28c1641af8..88425eed728 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected @@ -1,5 +1,5 @@ | a.js:1:11:1:28 | require('./b').foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:5:1:5:5 | b.foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:15:1:15:9 | fs.renmae | Module $@ does not export symbol renmae. | fs.js:1:1:15:0 | | fs | -| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:7:52 | | l | +| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:6:0 | | l | | multi_import.js:16:3:16:10 | mod2.bar | Module $@ does not export symbol bar. | b.js:1:1:5:21 | | b | diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js index f1cb91159f0..bd8e36c10e3 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js @@ -615,4 +615,4 @@ Array.some = function(arr, callback, opt_context) {}; */ Array.isArray = function(arr) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js index 3d097fb8ede..c475ea2262f 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js @@ -4,5 +4,4 @@ module.exports = me; }(module)); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); // ensure this is treated as Node.js code diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js index e4c633ecf31..fefe8f6b2e7 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js @@ -2,4 +2,4 @@ var fs = require('fs'); fs.move = fs.rename; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js index 9fc7f5f1343..7b5e87d891a 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js @@ -11,4 +11,4 @@ fs.rename; module.exports = fs; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js index abf7cc4034f..8eb1794ae7b 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js @@ -3,5 +3,3 @@ class C { } module.exports = C; - -// semmle-extractor-options: --abort-on-parse-errors \ No newline at end of file diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js index ac41c9e8511..9e1c24dfecc 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js @@ -5,5 +5,3 @@ var props = { module.exports = { ...props }; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js index 20c9961d626..3b29030a26f 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js +++ b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js @@ -1,4 +1,2 @@ import hipsterness from 'react'; import curry from 'lodash/function/curry'; - -//semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 9d4e7a7b8de..4839b585eb4 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -84,5 +84,3 @@ var bad16 = /(.|\n)*!/s; // GOOD var good8 = /([\w.]+)*/; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/options b/javascript/ql/test/query-tests/React/DirectStateMutation/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js index f1adc83643f..0d4d465638d 100644 --- a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js @@ -11,5 +11,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js index 7d5a881389c..f5acdc8d99a 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js @@ -19,5 +19,3 @@ class C2 extends React.Component { const { p1: p2 } = state } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js index dda64bc62e8..6db5702e2fc 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js @@ -166,5 +166,3 @@ class C11 extends React.Component { this.state.writeIn_getDerivedStateFromProps; // OK } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js index e1972ddec1f..d71aa7136da 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js @@ -72,5 +72,3 @@ class C6 extends React.Component { } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js index 126745e9444..b28ddabc9ca 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js @@ -8,5 +8,3 @@ app.get('/post/:id', async function(req, res) { // NOT OK new sql.Request().query("select * from mytable where id = '" + req.params.id + "'"); }); - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js index 7df5c6b4f3f..73cddfb3a6a 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js @@ -7,5 +7,3 @@ angular.module('myApp', ['ngRoute']) .controller('FindPost', function($routeParams) { db.get('SELECT * FROM Post WHERE id = "' + $routeParams.id + '"'); }); - -// semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d4930ad07cf..23e5a4a6b05 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -5,3 +5,8 @@ | tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here | | tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here | | tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here | +| tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | +| tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | +| tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | +| tst.js:107:10:107:53 | encodeD ... &") | This replacement may double-escape '&' characters from $@. | tst.js:107:10:107:30 | encodeD ... otes(s) | here | +| tst.js:115:10:115:47 | encodeQ ... &") | This replacement may double-escape '&' characters from $@. | tst.js:115:10:115:24 | encodeQuotes(s) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 19ab94d2691..9c69c837f6b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -69,3 +69,68 @@ function badEncode(s) { .replace(indirect2, "'") .replace(indirect3, "&"); } + +function badEscape1(s) { + return JSON.stringify( + s.replace(//g, "\\u003E") + ); +} + +function goodEscape1(s) { + return JSON.stringify(s) + .replace(//g, "\\u003E"); +} + +function badUnescape2(s) { + return JSON.parse(s).replace(/\\u003C/g, "<").replace(/\\u003E/g, ">"); +} + +function goodUnescape2(s) { + return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">")); +} + +function badEncodeWithReplacer(s) { + var repl = { + '"': """, + "'": "'", + "&": "&" + }; + return s.replace(/["']/g, (c) => repl[c]).replace(/&/g, "&"); +} + +function encodeDoubleQuotes(s) { + return s.replace(/"/g, """); +} + +function badWrappedEncode(s) { + return encodeDoubleQuotes(s).replace(/&/g, "&"); +} + +function encodeQuotes(s) { + return s.replace(/"/g, """).replace(/'/g, "'"); +} + +function badWrappedEncode2(s) { + return encodeQuotes(s).replace(/&/g, "&"); +} + +function roundtrip(s) { + return JSON.parse(JSON.stringify(s)); +} + +// dubious, but out of scope for this query +function badRoundtrip(s) { + return s.replace(/\\\\/g, "\\").replace(/\\/g, "\\\\"); +} + +function testWithCapturedVar(x) { + var captured = x; + (function() { + captured = captured.replace(/\\/g, "\\\\"); + })(); +} + +function cloneAndStringify(s) { + return JSON.stringify(JSON.parse(JSON.stringify(s))); +} diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected new file mode 100644 index 00000000000..9f5c5a0b082 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected @@ -0,0 +1,2 @@ +| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Result from call to concat ignored. | +| tst.js:5:1:5:15 | arr.concat(arr) | Result from call to concat ignored. | diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref new file mode 100644 index 00000000000..2cbc7e722a5 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref @@ -0,0 +1 @@ +Statements/IgnoreArrayResult.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js new file mode 100644 index 00000000000..47efe8c1cb6 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js @@ -0,0 +1,11 @@ +var arr = [1,2,3]; + +arr.concat([1,2,3]); // NOT OK! + +arr.concat(arr); // NOT OK! + +console.log(arr.concat([1,2,3])); + +({concat: Array.prototype.concat}.concat(arr)); + +[].concat([1,2,3]); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js index 3397ebd38a4..572dbe25035 100644 --- a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js +++ b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js @@ -1,5 +1,4 @@ // not a syntax error, but still NOT OK return 42; -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("path") // ensure this is treated as Node.js code diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 500d900ff9e..f23b702bf20 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,5 +1,7 @@ -| tst.js:20:17:20:33 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:24:13:24:29 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:30:20:30:36 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | bothOnlyHaveSideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | bothOnlyHaveSideEffects | +| tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | +| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | +| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 8bb49f7e761..90a52153dea 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -68,4 +68,24 @@ var h = returnsValue() || alwaysThrows(); // OK! console.log(h); + + function equals(x, y) { + return x === y; + } + + var foo = [1,2,3].filter(n => {equals(n, 3)}) // NOT OK! + console.log(foo); + + import { filter } from 'lodash' + var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK! + console.log(bar); + + var baz = [1,2,3].filter(n => {n === 3}) // OK + console.log(baz); + + class Deferred { + + } + + new Deferred().resolve(onlySideEffects()); // OK })(); \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js index 8731ac0cfac..a3e429ed0b5 100644 --- a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js @@ -176,5 +176,3 @@ async function awaitFlow(){ if (v) { // OK } }); - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/options b/javascript/ql/test/query-tests/Statements/UselessConditional/options new file mode 100644 index 00000000000..ae107b46f9e --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected index 7c583b1bf39..da235c205ee 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected @@ -39,8 +39,11 @@ | textmate.html:0:0:0:0 | textmate.html | generated | | tmpl2.html:0:0:0:0 | tmpl2.html | template | | tmpl.html:0:0:0:0 | tmpl.html | template | +| tst-min.js:0:0:0:0 | tst-min.js | generated | | tst.browserify.js:0:0:0:0 | tst.browserify.js | generated | | tst.dart.js:0:0:0:0 | tst.dart.js | generated | +| tst.min.js:0:0:0:0 | tst.min.js | generated | +| tst_min.js:0:0:0:0 | tst_min.js | generated | | twitter-text.js:0:0:0:0 | twitter-text.js | library | | twitter_text.js:0:0:0:0 | twitter_text.js | library | | unannotated-externs-1.js:0:0:0:0 | unannotated-externs-1.js | externs | diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js index ba9b39b4f72..5d56c9b782e 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js @@ -1,3 +1 @@ ๐Ÿ˜ผ๐Ÿ˜ผ - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/options b/javascript/ql/test/query-tests/filters/ClassifyFiles/options new file mode 100644 index 00000000000..13f987b19ca --- /dev/null +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html index 734e6cf7da8..671a0c7b51b 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html @@ -1,4 +1,3 @@ -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js index 1a42f3cf925..cda21380525 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js @@ -3,4 +3,3 @@ common.autofocus('#id_password'); {% else %} common.autofocus('#id_username'); {% endif %} -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html index c21d85208f5..e3bdc744425 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html @@ -5,4 +5,3 @@ common.autofocus('#id_password'); common.autofocus('#id_username'); {% endif %} -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html index 8e96a8b41f4..700fe9c08d2 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html @@ -5,4 +5,3 @@ {{/config}} } -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js index c53a0a15327..a54fda636cc 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js @@ -1,2 +1,2 @@ -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process") +; diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options new file mode 100644 index 00000000000..a1b2b21840f --- /dev/null +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors \ No newline at end of file diff --git a/python/ql/src/Classes/MethodCallOrder.qll b/python/ql/src/Classes/MethodCallOrder.qll index fe6ef07266a..5073cefc134 100644 --- a/python/ql/src/Classes/MethodCallOrder.qll +++ b/python/ql/src/Classes/MethodCallOrder.qll @@ -3,11 +3,16 @@ import python // Helper predicates for multiple call to __init__/__del__ queries. pragma [noinline] -private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +private predicate multiple_invocation_paths_helper(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { i1 != i2 and i1 = top.getACallee+() and i2 = top.getACallee+() and - i1.getFunction() = multi and + i1.getFunction() = multi +} + +pragma [noinline] +private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { + multiple_invocation_paths_helper(top, i1, i2, multi) and i2.getFunction() = multi } diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 3ac04e2e4d2..d5867aaaf46 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -13,17 +13,17 @@ import python import Variables.Definition -predicate global_name_used(Module m, Variable name) { +predicate global_name_used(Module m, string name) { exists(Name u, GlobalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m ) or // A use of an undefined class local variable, will use the global variable exists(Name u, LocalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m and not v.getScope().getEnclosingScope*() instanceof Function ) @@ -41,41 +41,58 @@ predicate all_not_understood(Module m) { } predicate imported_module_used_in_doctest(Import imp) { - exists(string modname | + exists(string modname, string docstring | imp.getAName().getAsname().(Name).getId() = modname and // Look for doctests containing the patterns: // >>> โ€ฆnameโ€ฆ // ... โ€ฆnameโ€ฆ - exists(StrConst doc | - doc.getEnclosingModule() = imp.getScope() and - doc.isDocString() and - doc.getText().regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") - ) + docstring = doctest_in_scope(imp.getScope()) and + docstring.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") + ) +} + +pragma[noinline] +private string doctest_in_scope(Scope scope) { + exists(StrConst doc | + doc.getEnclosingModule() = scope and + doc.isDocString() and + result = doc.getText() and + result.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.)[\\s\\S]*") + ) +} + +pragma[noinline] +private string typehint_annotation_in_file(File file) { + exists(StrConst annotation | + annotation = any(Arguments a).getAnAnnotation() + or + annotation = any(AnnAssign a).getAnnotation() + | + annotation.pointsTo(Value::forString(result)) and + file = annotation.getLocation().getFile() + ) +} + +pragma[noinline] +private string typehint_comment_in_file(File file) { + exists(Comment typehint | + file = typehint.getLocation().getFile() and + result = typehint.getText() and + result.matches("# type:%") ) } predicate imported_module_used_in_typehint(Import imp) { - exists(string modname, Location loc | + exists(string modname, File file | imp.getAName().getAsname().(Name).getId() = modname and - loc.getFile() = imp.getScope().(Module).getFile() + file = imp.getScope().(Module).getFile() | // Look for type hints containing the patterns: // # type: โ€ฆnameโ€ฆ - exists(Comment typehint | - loc = typehint.getLocation() and - typehint.getText().regexpMatch("# type:.*" + modname + ".*") - ) + typehint_comment_in_file(file).regexpMatch("# type:.*" + modname + ".*") or // Type hint is inside a string annotation, as needed for forward references - exists(string typehint, Expr annotation | - annotation = any(Arguments a).getAnAnnotation() - or - annotation = any(AnnAssign a).getAnnotation() - | - annotation.pointsTo(Value::forString(typehint)) and - loc = annotation.getLocation() and - typehint.regexpMatch(".*\\b" + modname + "\\b.*") - ) + typehint_annotation_in_file(file).regexpMatch(".*\\b" + modname + "\\b.*") ) } @@ -84,7 +101,7 @@ predicate unused_import(Import imp, Variable name) { not imp.getAnImportedModuleName() = "__future__" and not imp.getEnclosingModule().declaredInAll(name.getId()) and imp.getScope() = imp.getEnclosingModule() and - not global_name_used(imp.getScope(), name) and + not global_name_used(imp.getScope(), name.getId()) and // Imports in `__init__.py` are used to force module loading not imp.getEnclosingModule().isPackageInit() and // Name may be imported for use in epytext documentation diff --git a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index b542ae252eb..8eb0f43eb01 100644 --- a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -64,6 +64,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index 6c783a4f729..828c71153b5 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -80,6 +80,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp index 4497437aac1..5b4d21bb37e 100644 --- a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp +++ b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp @@ -38,7 +38,7 @@ Jinja2: API. Wikipedia: Cross-site scripting.
  • -OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet. +OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp index 8cdeb4d3e79..04a83fba6b4 100644 --- a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -31,7 +31,7 @@ The second view is safe as first_name is escaped, so it is not vuln
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-089/SqlInjection.qhelp b/python/ql/src/Security/CWE-089/SqlInjection.qhelp index e976401a6b5..63941706e84 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.qhelp +++ b/python/ql/src/Security/CWE-089/SqlInjection.qhelp @@ -21,20 +21,29 @@ or prepared statements.

    -In the following snippet, from an example django app, -a name is stored in the database using two different queries. +In the following snippet, a user is fetched from the database using three +different queries.

    In the first case, the query string is built by -directly using string formatting from a user-supplied request attribute. +directly using string formatting from a user-supplied request parameter. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.

    In the second case, the user-supplied request attribute is passed -to the database using query parameters. +to the database using query parameters. The database connector library will +take care of escaping and inserting quotes as needed. +

    + +

    +In the third case, the placeholder in the SQL string has been manually quoted. Since most +databaseconnector libraries will insert their own quotes, doing so yourself will make the code +vulnerable to SQL injection attacks. In this example, if username was +; DROP ALL TABLES -- , the final SQL query would be +SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''

    @@ -42,6 +51,6 @@ to the database using query parameters.
  • Wikipedia: SQL injection.
  • -
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • +
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-089/examples/sql_injection.py b/python/ql/src/Security/CWE-089/examples/sql_injection.py index 541c580f712..fe6dbc50c01 100644 --- a/python/ql/src/Security/CWE-089/examples/sql_injection.py +++ b/python/ql/src/Security/CWE-089/examples/sql_injection.py @@ -1,21 +1,19 @@ - -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + user = cursor.fetchone() - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + user = cursor.fetchone() + # BAD -- Manually quoting placeholder (%s) + cursor.execute("SELECT * FROM users WHERE username = '%s'", username) + user = cursor.fetchone() -urlpatterns = patterns(url(r'^save_name/$', - upload, name='save_name')) - +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] diff --git a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 6cc787e52e4..1b4031b1cc5 100644 --- a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -49,7 +49,7 @@
  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index f298e62695f..8c2660b9865 100644 --- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -49,7 +49,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp index c2e053f030b..756a43cc106 100644 --- a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp +++ b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/semmle/python/dataflow/Legacy.qll b/python/ql/src/semmle/python/dataflow/Legacy.qll index d401fc1a418..94dd55e20fa 100644 --- a/python/ql/src/semmle/python/dataflow/Legacy.qll +++ b/python/ql/src/semmle/python/dataflow/Legacy.qll @@ -33,26 +33,18 @@ private class LegacyConfiguration extends TaintTracking::Configuration { } override predicate isSource(TaintSource src) { - isValid() and src = src } override predicate isSink(TaintSink sink) { - isValid() and sink = sink } override predicate isSanitizer(Sanitizer sanitizer) { - isValid() and sanitizer = sanitizer } - private predicate isValid() { - not exists(TaintTracking::Configuration config | config != this) - } - override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node dest) { - isValid() and exists(DataFlowExtension::DataFlowNode legacyExtension | src.asCfgNode() = legacyExtension | @@ -67,7 +59,6 @@ private class LegacyConfiguration extends TaintTracking::Configuration { } override predicate isAdditionalFlowStep(DataFlow::Node src, DataFlow::Node dest, TaintKind srckind, TaintKind destkind) { - isValid() and exists(DataFlowExtension::DataFlowNode legacyExtension | src.asCfgNode() = legacyExtension | @@ -76,7 +67,6 @@ private class LegacyConfiguration extends TaintTracking::Configuration { } override predicate isBarrierEdge(DataFlow::Node src, DataFlow::Node dest) { - isValid() and ( exists(DataFlowExtension::DataFlowVariable legacyExtension | src.asVariable() = legacyExtension and @@ -91,4 +81,3 @@ private class LegacyConfiguration extends TaintTracking::Configuration { } } - diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll new file mode 100644 index 00000000000..423d853cdad --- /dev/null +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -0,0 +1,40 @@ +import python +import semmle.python.regex +import semmle.python.web.Http + +predicate django_route(CallNode call, ControlFlowNode regex, FunctionValue view) { + exists(FunctionValue url | + Value::named("django.conf.urls.url") = url and + url.getArgumentForCall(call, 0) = regex and + url.getArgumentForCall(call, 1).pointsTo(view) + ) +} + +class DjangoRouteRegex extends RegexString { + DjangoRouteRegex() { django_route(_, this.getAFlowNode(), _) } +} + +class DjangoRoute extends CallNode { + DjangoRoute() { django_route(this, _, _) } + + FunctionValue getViewFunction() { django_route(this, _, result) } + + string getNamedArgument() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + regex.getGroupName(_, _) = result + ) + } + + /** + * Get the number of positional arguments that will be passed to the view. + * Will only return a result if there are no named arguments. + */ + int getNumPositionalArguments() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + not exists(string s | s = regex.getGroupName(_, _)) and + result = count(regex.getGroupNumber(_, _)) + ) + } +} diff --git a/python/ql/src/semmle/python/web/django/Model.qll b/python/ql/src/semmle/python/web/django/Model.qll index 34cf5856802..b8f47b64bdf 100644 --- a/python/ql/src/semmle/python/web/django/Model.qll +++ b/python/ql/src/semmle/python/web/django/Model.qll @@ -54,33 +54,6 @@ class DjangoModelObjects extends TaintSource { override string toString() { result = "django.db.models.Model.objects" } } -/** A write to a field of a django model, which is a vulnerable to external data. */ -class DjangoModelFieldWrite extends SqlInjectionSink { - DjangoModelFieldWrite() { - exists(AttrNode attr, DjangoModel model | - this = attr and attr.isStore() and attr.getObject(_).pointsTo(model) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model field write" } -} - -/** A direct reference to a django model object, which is vulnerable to external data. */ -class DjangoModelDirectObjectReference extends TaintSink { - DjangoModelDirectObjectReference() { - exists(CallNode objects_get_call, ControlFlowNode objects | this = objects_get_call.getAnArg() | - objects_get_call.getFunction().(AttrNode).getObject("get") = objects and - any(DjangoDbTableObjects objs).taints(objects) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model object reference" } -} - /** * A call to the `raw` method on a django model. This allows a raw SQL query * to be sent to the database, which is a security risk. diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index d2ad2ff30d3..24a29ea4542 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -1,7 +1,7 @@ import python -import semmle.python.regex import semmle.python.security.TaintTracking import semmle.python.web.Http +import semmle.python.web.django.General /** A django.request.HttpRequest object */ class DjangoRequest extends TaintKind { @@ -52,7 +52,7 @@ abstract class DjangoRequestSource extends HttpRequestTaintSource { private class DjangoFunctionBasedViewRequestArgument extends DjangoRequestSource { DjangoFunctionBasedViewRequestArgument() { exists(FunctionValue view | - url_dispatch(_, _, view) and + django_route(_, _, view) and this = view.getScope().getArg(0).asName().getAFlowNode() ) } @@ -67,7 +67,7 @@ private class DjangoView extends ClassValue { } private FunctionValue djangoViewHttpMethod() { - exists(DjangoView view | view.attr(httpVerbLower()) = result) + exists(DjangoView view | view.lookup(httpVerbLower()) = result) } class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { @@ -76,41 +76,18 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { } } -/* *********** Routing ********* */ -/* Function based views */ -predicate url_dispatch(CallNode call, ControlFlowNode regex, FunctionValue view) { - exists(FunctionValue url | - Value::named("django.conf.urls.url") = url and - url.getArgumentForCall(call, 0) = regex and - url.getArgumentForCall(call, 1).pointsTo(view) - ) -} - -class UrlRegex extends RegexString { - UrlRegex() { url_dispatch(_, this.getAFlowNode(), _) } -} - -class UrlRouting extends CallNode { - UrlRouting() { url_dispatch(this, _, _) } - - FunctionValue getViewFunction() { url_dispatch(this, _, result) } - - string getNamedArgument() { - exists(UrlRegex regex | - url_dispatch(this, regex.getAFlowNode(), _) and - regex.getGroupName(_, _) = result - ) - } -} - /** An argument specified in a url routing table */ -class HttpRequestParameter extends HttpRequestTaintSource { - HttpRequestParameter() { - exists(UrlRouting url | - this.(ControlFlowNode).getNode() = url - .getViewFunction() - .getScope() - .getArgByName(url.getNamedArgument()) +class DjangoRequestParameter extends HttpRequestTaintSource { + DjangoRequestParameter() { + exists(DjangoRoute route, Function f | + f = route.getViewFunction().getScope() | + this.(ControlFlowNode).getNode() = f.getArgByName(route.getNamedArgument()) + or + exists(int i | i >= 0 | + i < route.getNumPositionalArguments() and + // +1 because first argument is always the request + this.(ControlFlowNode).getNode() = f.getArg(i+1) + ) ) } diff --git a/python/ql/test/2/library-tests/classes/attr/list_attr.expected b/python/ql/test/2/library-tests/classes/attr/list_attr.expected index b281b8f9e9a..4668766c5e5 100644 --- a/python/ql/test/2/library-tests/classes/attr/list_attr.expected +++ b/python/ql/test/2/library-tests/classes/attr/list_attr.expected @@ -1,9 +1,12 @@ | builtin-class list | __add__ | Builtin-method __add__ | +| builtin-class list | __class__ | Property __class__ | | builtin-class list | __contains__ | Builtin-method __contains__ | +| builtin-class list | __delattr__ | Builtin-method __delattr__ | | builtin-class list | __delitem__ | Builtin-method __delitem__ | | builtin-class list | __delslice__ | Builtin-method __delslice__ | | builtin-class list | __doc__ | str b'list() -> new empty list\nlist(iterable) -> new list initialized from iterable's items' | | builtin-class list | __eq__ | Builtin-method __eq__ | +| builtin-class list | __format__ | Builtin-method __format__ | | builtin-class list | __ge__ | Builtin-method __ge__ | | builtin-class list | __getattribute__ | Builtin-method __getattribute__ | | builtin-class list | __getitem__ | Builtin-method __getitem__ | @@ -20,12 +23,17 @@ | builtin-class list | __mul__ | Builtin-method __mul__ | | builtin-class list | __ne__ | Builtin-method __ne__ | | builtin-class list | __new__ | builtin_function_or_method __new__ | +| builtin-class list | __reduce__ | Builtin-method __reduce__ | +| builtin-class list | __reduce_ex__ | Builtin-method __reduce_ex__ | | builtin-class list | __repr__ | Builtin-method __repr__ | | builtin-class list | __reversed__ | Builtin-method __reversed__ | | builtin-class list | __rmul__ | Builtin-method __rmul__ | +| builtin-class list | __setattr__ | Builtin-method __setattr__ | | builtin-class list | __setitem__ | Builtin-method __setitem__ | | builtin-class list | __setslice__ | Builtin-method __setslice__ | | builtin-class list | __sizeof__ | Builtin-method __sizeof__ | +| builtin-class list | __str__ | Builtin-method __str__ | +| builtin-class list | __subclasshook__ | classmethod_descriptor __subclasshook__ | | builtin-class list | append | Builtin-method append | | builtin-class list | count | Builtin-method count | | builtin-class list | extend | Builtin-method extend | diff --git a/python/ql/test/2/library-tests/classes/mro/C3.expected b/python/ql/test/2/library-tests/classes/mro/C3.expected index bd86482f34d..d55fae894de 100644 --- a/python/ql/test/2/library-tests/classes/mro/C3.expected +++ b/python/ql/test/2/library-tests/classes/mro/C3.expected @@ -3,7 +3,6 @@ | class C | [C, BaseException, object] | | class D | [D, X, object] | | class Meta | [Meta, type, object] | -| class N | [N, object, O] | | class NewStyle | [NewStyle, object] | | class NewStyleDerived | [NewStyleDerived, NewStyle, object] | | class O | [O] | diff --git a/python/ql/test/2/library-tests/classes/mro/mro.expected b/python/ql/test/2/library-tests/classes/mro/mro.expected index 41db9554fe1..aab6cc1a001 100644 --- a/python/ql/test/2/library-tests/classes/mro/mro.expected +++ b/python/ql/test/2/library-tests/classes/mro/mro.expected @@ -8,8 +8,6 @@ | class D | class X | builtin-class object | | class Meta | builtin-class type | builtin-class object | | class Meta | class Meta | builtin-class type | -| class N | builtin-class object | class O | -| class N | class N | builtin-class object | | class NewStyle | class NewStyle | builtin-class object | | class NewStyleDerived | class NewStyle | builtin-class object | | class NewStyleDerived | class NewStyleDerived | class NewStyle | diff --git a/python/ql/test/2/library-tests/six/test.expected b/python/ql/test/2/library-tests/six/test.expected index 8462f2b2464..50ad5bc7e57 100644 --- a/python/ql/test/2/library-tests/six/test.expected +++ b/python/ql/test/2/library-tests/six/test.expected @@ -1,5 +1,6 @@ | Module six | BytesIO | class StringIO | | Module six | Iterator | class Iterator | +| Module six | MAXSIZE | int() | | Module six | PY2 | bool True | | Module six | PY3 | bool False | | Module six | StringIO | class StringIO | @@ -45,14 +46,6 @@ | Module six | iterlists | Function iterlists | | Module six | itervalues | Function itervalues | | Module six | moves | Module six.moves | -| Module six | moves.__init__ | Module six.moves.__init__ | -| Module six | moves.urllib | Module six.moves.urllib | -| Module six | moves.urllib.__init__ | Module six.moves.urllib.__init__ | -| Module six | moves.urllib_error | Module six.moves.urllib_error | -| Module six | moves.urllib_parse | Module six.moves.urllib_parse | -| Module six | moves.urllib_request | Module six.moves.urllib_request | -| Module six | moves.urllib_response | Module six.moves.urllib_response | -| Module six | moves.urllib_robotparser | Module six.moves.urllib_robotparser | | Module six | next | Builtin-function next | | Module six | operator | Module operator | | Module six | print_ | Function print_ | @@ -67,6 +60,7 @@ | Module six | with_metaclass | Function with_metaclass | | Module six.__init__ | BytesIO | class StringIO | | Module six.__init__ | Iterator | class Iterator | +| Module six.__init__ | MAXSIZE | int() | | Module six.__init__ | PY2 | bool True | | Module six.__init__ | PY3 | bool False | | Module six.__init__ | StringIO | class StringIO | @@ -174,7 +168,6 @@ | Module six.moves | tkinter_tksimpledialog | Module tkSimpleDialog | | Module six.moves | tkinter_ttk | Module ttk | | Module six.moves | urllib | Module six.moves.urllib | -| Module six.moves | urllib.__init__ | Module six.moves.urllib.__init__ | | Module six.moves | urllib_error | Module six.moves.urllib_error | | Module six.moves | urllib_parse | Module six.moves.urllib_parse | | Module six.moves | urllib_request | Module six.moves.urllib_request | diff --git a/python/ql/test/2/library-tests/types/classes/mro_test.expected b/python/ql/test/2/library-tests/types/classes/mro_test.expected index b1aa3af843e..6c1d3b50bf2 100644 --- a/python/ql/test/2/library-tests/types/classes/mro_test.expected +++ b/python/ql/test/2/library-tests/types/classes/mro_test.expected @@ -1,3 +1,5 @@ +| class A | [A, ??, object] | +| class J | [J, ??, object] | | class MyDict | [MyDict, dict, object] | | class MyList | [MyList, list, object] | | class O1 | [O1] | diff --git a/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrHash.expected b/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrHash.expected index aaed9443525..916a9bb4454 100644 --- a/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrHash.expected +++ b/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrHash.expected @@ -1,2 +1,2 @@ -| equals_hash.py:8:5:8:28 | Function __eq__ | Class $@ implements __eq__ but does not define __hash__. | equals_hash.py:3:1:3:17 | class Eq | Eq | -| equals_hash.py:24:5:24:23 | Function __hash__ | Class $@ implements __hash__ but does not define __eq__ or __cmp__. | equals_hash.py:19:1:19:19 | class Hash | Hash | +| equals_hash.py:8:5:8:28 | Function Eq.__eq__ | Class $@ implements __eq__ but does not define __hash__. | equals_hash.py:3:1:3:17 | class Eq | Eq | +| equals_hash.py:24:5:24:23 | Function Hash.__hash__ | Class $@ implements __hash__ but does not define __eq__ or __cmp__. | equals_hash.py:19:1:19:19 | class Hash | Hash | diff --git a/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrNotEquals.expected b/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrNotEquals.expected index a7ac0084132..04e395c668b 100644 --- a/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrNotEquals.expected +++ b/python/ql/test/2/query-tests/Classes/equals-hash/EqualsOrNotEquals.expected @@ -1,2 +1,2 @@ -| equals_hash.py:8:5:8:28 | Function __eq__ | Class $@ implements __eq__ but does not implement __ne__. | equals_hash.py:3:1:3:17 | class Eq | Eq | -| equals_hash.py:16:5:16:28 | Function __ne__ | Class $@ implements __ne__ but does not implement __eq__. | equals_hash.py:11:1:11:17 | class Ne | Ne | +| equals_hash.py:8:5:8:28 | Function Eq.__eq__ | Class $@ implements __eq__ but does not implement __ne__. | equals_hash.py:3:1:3:17 | class Eq | Eq | +| equals_hash.py:16:5:16:28 | Function Ne.__ne__ | Class $@ implements __ne__ but does not implement __eq__. | equals_hash.py:11:1:11:17 | class Ne | Ne | diff --git a/python/ql/test/3/library-tests/web/django/Sinks.expected b/python/ql/test/3/library-tests/web/django/Sinks.expected deleted file mode 100644 index b4142a2d82a..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.expected +++ /dev/null @@ -1,6 +0,0 @@ -| models.py:9 | key | externally controlled string | -| rawsql.py:4 | BinaryExpr | externally controlled string | -| rawsql.py:13 | BinaryExpr | externally controlled string | -| rawsql.py:18 | BinaryExpr | externally controlled string | -| rawsql.py:22 | BinaryExpr | externally controlled string | -| views.py:8 | Attribute() | externally controlled string | diff --git a/python/ql/test/3/library-tests/web/django/Sinks.ql b/python/ql/test/3/library-tests/web/django/Sinks.ql deleted file mode 100644 index db9b6a89b93..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.ql +++ /dev/null @@ -1,13 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Db -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Sources.expected b/python/ql/test/3/library-tests/web/django/Sources.expected deleted file mode 100644 index 965142343dc..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.expected +++ /dev/null @@ -1,8 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Sources.ql b/python/ql/test/3/library-tests/web/django/Sources.ql deleted file mode 100644 index 60d42cb2ac1..00000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.ql +++ /dev/null @@ -1,12 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Taint.expected b/python/ql/test/3/library-tests/web/django/Taint.expected deleted file mode 100644 index 3f40979c8a2..00000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.expected +++ /dev/null @@ -1,24 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute() | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | m | django.db.models.Model.objects | -| rawsql.py:18 | Attribute() | django.db.models.Model.objects | -| rawsql.py:18 | m | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | m | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | Attribute | django.http.request.QueryDict | -| views.py:8 | Attribute() | externally controlled string | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:8 | request | django.request.HttpRequest | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | -| views.py:12 | Dict | {externally controlled string} | -| views.py:12 | path | externally controlled string | -| views.py:13 | env | {externally controlled string} | -| views.py:13 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Taint.ql b/python/ql/test/3/library-tests/web/django/Taint.ql deleted file mode 100644 index b12a6560125..00000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.ql +++ /dev/null @@ -1,14 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - - -from TaintedNode node - -select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind().toString() - diff --git a/python/ql/test/3/library-tests/web/django/django/__init__.py b/python/ql/test/3/library-tests/web/django/django/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py b/python/ql/test/3/library-tests/web/django/django/conf/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/urls.py b/python/ql/test/3/library-tests/web/django/django/conf/urls.py deleted file mode 100644 index 580cc063d99..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/urls.py +++ /dev/null @@ -1,3 +0,0 @@ - -def url(regex, view): - pass \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/__init__.py deleted file mode 100644 index fc8d5b8c09b..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py deleted file mode 100644 index eb9c72adc45..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -class Model: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py b/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py deleted file mode 100644 index d7e0d1c27b6..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py +++ /dev/null @@ -1,2 +0,0 @@ -class RawSQL: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/http/__init__.py b/python/ql/test/3/library-tests/web/django/django/http/__init__.py deleted file mode 100644 index e1a02f873cb..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -from .response import HttpResponse diff --git a/python/ql/test/3/library-tests/web/django/django/http/response.py b/python/ql/test/3/library-tests/web/django/django/http/response.py deleted file mode 100644 index f3dd53d15b0..00000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/response.py +++ /dev/null @@ -1,5 +0,0 @@ - -class HttpResponse: - - def __init__(self, *args): - pass diff --git a/python/ql/test/3/library-tests/web/django/models.py b/python/ql/test/3/library-tests/web/django/models.py deleted file mode 100644 index 571c594d055..00000000000 --- a/python/ql/test/3/library-tests/web/django/models.py +++ /dev/null @@ -1,10 +0,0 @@ - -from django.db import models - -class MyModel(models.Model): - title = models.CharField(max_length=500) - summary = models.TextField(blank=True) - -def update_my_model(key, title): - item = MyModel.objects.get(pk=key) - item.title = title diff --git a/python/ql/test/3/library-tests/web/django/rawsql.py b/python/ql/test/3/library-tests/web/django/rawsql.py deleted file mode 100644 index c6c82909c2d..00000000000 --- a/python/ql/test/3/library-tests/web/django/rawsql.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.db.models.expressions import RawSQL - -def raw1(arg): - return RawSQL("select foo from bar where baz = %s" % arg, "") - - -from django.db import models - -class MyModel(models.Model): - pass - -def raw2(arg): - MyModel.objects.raw("select foo from bar where baz = %s" % arg) - -def raw3(arg): - m = MyModel.objects.filter('foo') - m = m.filter('bar') - m.raw("select foo from bar where baz = %s" % arg) - -def raw4(arg): - m = MyModel.objects.filter('foo') - m.extra("select foo from bar where baz = %s" % arg) - diff --git a/python/ql/test/3/library-tests/web/django/urls.py b/python/ql/test/3/library-tests/web/django/urls.py deleted file mode 100644 index d5a941ae519..00000000000 --- a/python/ql/test/3/library-tests/web/django/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.conf.urls import url -import views - -urlpatterns = [ - - url(r'^route1$', views.view_func1), - url(r'^(?P.*)$', views.view_func2), - url(r'^route2$', views.ClassView.as_view()) -] diff --git a/python/ql/test/3/library-tests/web/django/views.py b/python/ql/test/3/library-tests/web/django/views.py deleted file mode 100644 index f7de60a23f6..00000000000 --- a/python/ql/test/3/library-tests/web/django/views.py +++ /dev/null @@ -1,19 +0,0 @@ - -from django.http import HttpResponse -from django.shortcuts import redirect, render -from django.views.generic import View - -def view_func1(request): - # Whether this is safe depends on template.html -- annoyingly - return HttpResponse(request.GET.get("untrusted")) - - -def view_func2(request, path='default'): - env = {'path': path} - return render(request, 'vulnerable-path.html', env) - - -class ClassView(View): - - def get(self, request): - pass diff --git a/python/ql/test/3/library-tests/web/options b/python/ql/test/3/library-tests/web/options deleted file mode 100644 index f2d60a4bc3c..00000000000 --- a/python/ql/test/3/library-tests/web/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 --lang=3 diff --git a/python/ql/test/library-tests/taint/config/RockPaperScissors.expected b/python/ql/test/library-tests/taint/config/RockPaperScissors.expected index 9e8ed503047..0639e4bf227 100644 --- a/python/ql/test/library-tests/taint/config/RockPaperScissors.expected +++ b/python/ql/test/library-tests/taint/config/RockPaperScissors.expected @@ -28,6 +28,12 @@ edges | rockpaperscissors.py:25:9:25:9 | rock | rockpaperscissors.py:25:9:25:16 | scissors | | rockpaperscissors.py:25:9:25:16 | scissors | rockpaperscissors.py:25:9:25:23 | paper | | rockpaperscissors.py:25:9:25:23 | paper | rockpaperscissors.py:26:14:26:14 | paper | +| sanitizer.py:9:9:9:20 | SQL injection | sanitizer.py:13:19:13:19 | SQL injection | +| sanitizer.py:16:9:16:20 | Command injection | sanitizer.py:20:20:20:20 | Command injection | +| sanitizer.py:24:9:24:20 | SQL injection | sanitizer.py:26:19:26:19 | SQL injection | +| sanitizer.py:24:9:24:20 | SQL injection | sanitizer.py:28:19:28:19 | SQL injection | +| sanitizer.py:31:9:31:20 | Command injection | sanitizer.py:33:20:33:20 | Command injection | +| sanitizer.py:31:9:31:20 | Command injection | sanitizer.py:35:20:35:20 | Command injection | | test.py:6:9:6:14 | simple.test | test.py:7:10:7:10 | simple.test | | test.py:10:12:10:17 | simple.test | test.py:16:9:16:16 | simple.test | | test.py:10:12:10:17 | simple.test | test.py:24:9:24:16 | simple.test | diff --git a/python/ql/test/library-tests/taint/config/Simple.expected b/python/ql/test/library-tests/taint/config/Simple.expected index 6c2b87aa31e..108f0f12015 100644 --- a/python/ql/test/library-tests/taint/config/Simple.expected +++ b/python/ql/test/library-tests/taint/config/Simple.expected @@ -28,6 +28,12 @@ edges | rockpaperscissors.py:25:9:25:9 | rock | rockpaperscissors.py:25:9:25:16 | scissors | | rockpaperscissors.py:25:9:25:16 | scissors | rockpaperscissors.py:25:9:25:23 | paper | | rockpaperscissors.py:25:9:25:23 | paper | rockpaperscissors.py:26:14:26:14 | paper | +| sanitizer.py:9:9:9:20 | SQL injection | sanitizer.py:13:19:13:19 | SQL injection | +| sanitizer.py:16:9:16:20 | Command injection | sanitizer.py:20:20:20:20 | Command injection | +| sanitizer.py:24:9:24:20 | SQL injection | sanitizer.py:26:19:26:19 | SQL injection | +| sanitizer.py:24:9:24:20 | SQL injection | sanitizer.py:28:19:28:19 | SQL injection | +| sanitizer.py:31:9:31:20 | Command injection | sanitizer.py:33:20:33:20 | Command injection | +| sanitizer.py:31:9:31:20 | Command injection | sanitizer.py:35:20:35:20 | Command injection | | test.py:6:9:6:14 | simple.test | test.py:7:10:7:10 | simple.test | | test.py:10:12:10:17 | simple.test | test.py:16:9:16:16 | simple.test | | test.py:10:12:10:17 | simple.test | test.py:24:9:24:16 | simple.test | diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 82d1b71e53a..e3d233c9990 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -1,6 +1,16 @@ -| test.py:18 | Str | externally controlled string | -| test.py:21 | BinaryExpr | externally controlled string | -| test.py:24 | BinaryExpr | externally controlled string | -| test.py:25 | BinaryExpr | externally controlled string | -| test.py:26 | BinaryExpr | externally controlled string | -| test.py:34 | BinaryExpr | externally controlled string | +| sql.py:13 | Str | externally controlled string | +| sql.py:14 | Str | externally controlled string | +| sql.py:17 | BinaryExpr | externally controlled string | +| sql.py:20 | BinaryExpr | externally controlled string | +| sql.py:21 | BinaryExpr | externally controlled string | +| sql.py:22 | BinaryExpr | externally controlled string | +| sql.py:36 | Str | externally controlled string | +| sql.py:42 | BinaryExpr | externally controlled string | +| sql.py:47 | BinaryExpr | externally controlled string | +| views.py:7 | Attribute() | externally controlled string | +| views.py:11 | Attribute() | externally controlled string | +| views.py:15 | Attribute() | externally controlled string | +| views.py:23 | Attribute() | externally controlled string | +| views.py:29 | Attribute() | externally controlled string | +| views.py:34 | Attribute() | externally controlled string | +| views.py:38 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 8f421a2d169..35e0d3d8ced 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,2 +1,19 @@ +| test.py:5 | path | externally controlled string | +| test.py:5 | request | django.request.HttpRequest | +| test.py:11 | path | externally controlled string | | test.py:11 | request | django.request.HttpRequest | -| test.py:31 | request | django.request.HttpRequest | +| views.py:6 | bar | externally controlled string | +| views.py:6 | foo | externally controlled string | +| views.py:6 | request | django.request.HttpRequest | +| views.py:10 | request | django.request.HttpRequest | +| views.py:14 | request | django.request.HttpRequest | +| views.py:22 | request | django.request.HttpRequest | +| views.py:28 | request | django.request.HttpRequest | +| views.py:32 | page_number | externally controlled string | +| views.py:32 | request | django.request.HttpRequest | +| views.py:37 | arg0 | externally controlled string | +| views.py:37 | arg1 | externally controlled string | +| views.py:37 | request | django.request.HttpRequest | +| views.py:57 | request | django.request.HttpRequest | +| views.py:57 | username | externally controlled string | +| views.py:66 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/sql.py b/python/ql/test/library-tests/web/django/sql.py new file mode 100644 index 00000000000..7809c24edc1 --- /dev/null +++ b/python/ql/test/library-tests/web/django/sql.py @@ -0,0 +1,53 @@ +from django.db import connection, models +from django.db.models.expressions import RawSQL + + +class User(models.Model): + username = models.CharField(max_length=100) + description = models.TextField(blank=True) + + +def show_user(username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) + + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) + + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) + + +def raw3(arg): + m = User.objects.filter('foo') + m = m.filter('bar') + m.raw("select foo from bar where baz = %s" % arg) + + +def raw4(arg): + m = User.objects.filter('foo') + m.extra("select foo from bar where baz = %s" % arg) + + +def update_user(key, description1): + # Neither of these are exposed to sql-injections + user = User.objects.get(pk=key) + item.description = description diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index e6c39c30a32..5664647c3a7 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -1,40 +1,18 @@ +from django.conf.urls import url +from django.shortcuts import redirect, render -from django.conf.urls import patterns, url -from django.db import connection, models -from django.db.models.expressions import RawSQL -from django.http.response import HttpResponse -import base64 -class Name(models.Model): - pass +def with_template(request, path='default'): + env = {'path': path} + # We would need to understand django templates to know if this is safe or not + return render(request, 'possibly-vulnerable-template.html', env) -def save_name(request): - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) +def vuln_redirect(request, path): + return redirect(path) - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) -urlpatterns1 = patterns(url(r'^save_name/$', - save_name, name='save_name')) - -def maybe_xss(request): - first_name = request.POST.get('first_name', '') - resp = HttpResponse() - resp.write("first name is " + first_name) - return resp - -urlpatterns2 = [ - # Route to code_execution - url(r'^maybe_xss$', maybe_xss, name='maybe_xss') +urlpatterns = [ + url(r'^(?P.*)$', with_template), + url(r'^redirect/(?P.*)$', vuln_redirect), ] diff --git a/python/ql/test/library-tests/web/django/views.py b/python/ql/test/library-tests/web/django/views.py new file mode 100644 index 00000000000..57d1ea5460c --- /dev/null +++ b/python/ql/test/library-tests/web/django/views.py @@ -0,0 +1,72 @@ +from django.conf.urls import patterns, url +from django.http.response import HttpResponse +from django.views.generic import View + + +def url_match_xss(request, foo, bar, no_taint=None): + return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) + + +def get_params_xss(request): + return HttpResponse(request.GET.get("untrusted")) + + +def post_params_xss(request): + return HttpResponse(request.POST.get("untrusted")) + + +class Foo(object): + # Note: since Foo is used as the super type in a class view, it will be able to handle requests. + + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def post(self, request, untrusted): + return HttpResponse('Foo post: {}'.format(untrusted)) + + +class ClassView(View, Foo): + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def get(self, request, untrusted): + return HttpResponse('ClassView get: {}'.format(untrusted)) + + +def show_articles(request, page_number=1): + page_number = int(page_number) + return HttpResponse('articles page: {}'.format(page_number)) + + +def xxs_positional_arg(request, arg0, arg1, no_taint=None): + return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) + + +urlpatterns = [ + url(r'^url_match/(?P[^/]+)/(?P[^/]+)$', url_match_xss), + url(r'^get_params$', get_params_xss), + url(r'^post_params$', post_params_xss), + url(r'^class_view/(?P.+)$', ClassView.as_view()), + + # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 + url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), + # passing as positional argument is not the recommended way of doing things, but it is certainly + # possible + url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg, name='xxs_positional_arg'), +] + + +# Using patterns() for routing + +def show_user(request, username): + pass + + +urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) + + +# Show we understand the keyword arguments to django.conf.urls.url + +def we_understand_url_kwargs(request): + pass + + +urlpatterns = [ + url(view=we_understand_url_kwargs, regex=r'^specifying-as-kwargs-is-not-a-problem$') +] diff --git a/python/ql/test/query-tests/Security/CWE-022/PathInjection.expected b/python/ql/test/query-tests/Security/CWE-022/PathInjection.expected index 646b22edea4..3cf398a025e 100644 --- a/python/ql/test/query-tests/Security/CWE-022/PathInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-022/PathInjection.expected @@ -1,16 +1,29 @@ edges | path_injection.py:9:12:9:23 | dict of externally controlled string | path_injection.py:9:12:9:39 | externally controlled string | +| path_injection.py:9:12:9:23 | dict of externally controlled string | path_injection.py:9:12:9:39 | externally controlled string | +| path_injection.py:9:12:9:39 | externally controlled string | path_injection.py:10:40:10:43 | externally controlled string | | path_injection.py:9:12:9:39 | externally controlled string | path_injection.py:10:40:10:43 | externally controlled string | | path_injection.py:10:40:10:43 | externally controlled string | path_injection.py:10:14:10:44 | externally controlled string | +| path_injection.py:10:40:10:43 | externally controlled string | path_injection.py:10:14:10:44 | externally controlled string | +| path_injection.py:15:12:15:23 | dict of externally controlled string | path_injection.py:15:12:15:39 | externally controlled string | | path_injection.py:15:12:15:23 | dict of externally controlled string | path_injection.py:15:12:15:39 | externally controlled string | | path_injection.py:15:12:15:39 | externally controlled string | path_injection.py:16:56:16:59 | externally controlled string | +| path_injection.py:15:12:15:39 | externally controlled string | path_injection.py:16:56:16:59 | externally controlled string | +| path_injection.py:16:13:16:61 | normalized path | path_injection.py:17:14:17:18 | normalized path | | path_injection.py:16:13:16:61 | normalized path | path_injection.py:17:14:17:18 | normalized path | | path_injection.py:16:30:16:60 | externally controlled string | path_injection.py:16:13:16:61 | normalized path | +| path_injection.py:16:30:16:60 | externally controlled string | path_injection.py:16:13:16:61 | normalized path | +| path_injection.py:16:56:16:59 | externally controlled string | path_injection.py:16:30:16:60 | externally controlled string | | path_injection.py:16:56:16:59 | externally controlled string | path_injection.py:16:30:16:60 | externally controlled string | | path_injection.py:24:12:24:23 | dict of externally controlled string | path_injection.py:24:12:24:39 | externally controlled string | +| path_injection.py:24:12:24:23 | dict of externally controlled string | path_injection.py:24:12:24:39 | externally controlled string | +| path_injection.py:24:12:24:39 | externally controlled string | path_injection.py:25:56:25:59 | externally controlled string | | path_injection.py:24:12:24:39 | externally controlled string | path_injection.py:25:56:25:59 | externally controlled string | | path_injection.py:25:13:25:61 | normalized path | path_injection.py:28:14:28:18 | normalized path | +| path_injection.py:25:13:25:61 | normalized path | path_injection.py:28:14:28:18 | normalized path | | path_injection.py:25:30:25:60 | externally controlled string | path_injection.py:25:13:25:61 | normalized path | +| path_injection.py:25:30:25:60 | externally controlled string | path_injection.py:25:13:25:61 | normalized path | +| path_injection.py:25:56:25:59 | externally controlled string | path_injection.py:25:30:25:60 | externally controlled string | | path_injection.py:25:56:25:59 | externally controlled string | path_injection.py:25:30:25:60 | externally controlled string | #select | path_injection.py:10:14:10:44 | Attribute() | path_injection.py:9:12:9:23 | dict of externally controlled string | path_injection.py:10:14:10:44 | externally controlled string | This path depends on $@. | path_injection.py:9:12:9:23 | Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-022/TarSlip.expected b/python/ql/test/query-tests/Security/CWE-022/TarSlip.expected index d1ddd948a43..73e28287dcf 100644 --- a/python/ql/test/query-tests/Security/CWE-022/TarSlip.expected +++ b/python/ql/test/query-tests/Security/CWE-022/TarSlip.expected @@ -1,11 +1,19 @@ edges | tarslip.py:12:7:12:39 | tarfile.open | tarslip.py:13:1:13:3 | tarfile.open | +| tarslip.py:12:7:12:39 | tarfile.open | tarslip.py:13:1:13:3 | tarfile.open | +| tarslip.py:16:7:16:39 | tarfile.open | tarslip.py:17:14:17:16 | tarfile.open | | tarslip.py:16:7:16:39 | tarfile.open | tarslip.py:17:14:17:16 | tarfile.open | | tarslip.py:17:1:17:17 | tarfile.entry | tarslip.py:18:17:18:21 | tarfile.entry | +| tarslip.py:17:1:17:17 | tarfile.entry | tarslip.py:18:17:18:21 | tarfile.entry | +| tarslip.py:17:14:17:16 | tarfile.open | tarslip.py:17:1:17:17 | tarfile.entry | | tarslip.py:17:14:17:16 | tarfile.open | tarslip.py:17:1:17:17 | tarfile.entry | | tarslip.py:33:7:33:39 | tarfile.open | tarslip.py:34:14:34:16 | tarfile.open | +| tarslip.py:33:7:33:39 | tarfile.open | tarslip.py:34:14:34:16 | tarfile.open | +| tarslip.py:34:1:34:17 | tarfile.entry | tarslip.py:37:17:37:21 | tarfile.entry | | tarslip.py:34:1:34:17 | tarfile.entry | tarslip.py:37:17:37:21 | tarfile.entry | | tarslip.py:34:14:34:16 | tarfile.open | tarslip.py:34:1:34:17 | tarfile.entry | +| tarslip.py:34:14:34:16 | tarfile.open | tarslip.py:34:1:34:17 | tarfile.entry | +| tarslip.py:40:7:40:39 | tarfile.open | tarslip.py:41:24:41:26 | tarfile.open | | tarslip.py:40:7:40:39 | tarfile.open | tarslip.py:41:24:41:26 | tarfile.open | #select | tarslip.py:13:1:13:3 | tar | tarslip.py:12:7:12:39 | tarfile.open | tarslip.py:13:1:13:3 | tarfile.open | Extraction of tarfile from $@ | tarslip.py:12:7:12:39 | Attribute() | a potentially untrusted source | diff --git a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected index d3b67cc239d..3d1cf22a2d1 100644 --- a/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-078/CommandInjection.expected @@ -1,15 +1,27 @@ edges | command_injection.py:10:13:10:24 | dict of externally controlled string | command_injection.py:10:13:10:41 | externally controlled string | +| command_injection.py:10:13:10:24 | dict of externally controlled string | command_injection.py:10:13:10:41 | externally controlled string | +| command_injection.py:10:13:10:41 | externally controlled string | command_injection.py:12:23:12:27 | externally controlled string | | command_injection.py:10:13:10:41 | externally controlled string | command_injection.py:12:23:12:27 | externally controlled string | | command_injection.py:12:23:12:27 | externally controlled string | command_injection.py:12:15:12:27 | externally controlled string | +| command_injection.py:12:23:12:27 | externally controlled string | command_injection.py:12:15:12:27 | externally controlled string | +| command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:17:13:17:41 | externally controlled string | | command_injection.py:17:13:17:24 | dict of externally controlled string | command_injection.py:17:13:17:41 | externally controlled string | | command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:29:19:33 | externally controlled string | +| command_injection.py:17:13:17:41 | externally controlled string | command_injection.py:19:29:19:33 | externally controlled string | +| command_injection.py:19:29:19:33 | externally controlled string | command_injection.py:19:22:19:34 | sequence of externally controlled string | | command_injection.py:19:29:19:33 | externally controlled string | command_injection.py:19:22:19:34 | sequence of externally controlled string | | command_injection.py:24:11:24:22 | dict of externally controlled string | command_injection.py:24:11:24:37 | externally controlled string | +| command_injection.py:24:11:24:22 | dict of externally controlled string | command_injection.py:24:11:24:37 | externally controlled string | +| command_injection.py:24:11:24:37 | externally controlled string | command_injection.py:25:23:25:25 | externally controlled string | | command_injection.py:24:11:24:37 | externally controlled string | command_injection.py:25:23:25:25 | externally controlled string | | command_injection.py:25:23:25:25 | externally controlled string | command_injection.py:25:22:25:36 | first item in sequence of externally controlled string | +| command_injection.py:25:23:25:25 | externally controlled string | command_injection.py:25:22:25:36 | first item in sequence of externally controlled string | +| command_injection.py:30:13:30:24 | dict of externally controlled string | command_injection.py:30:13:30:41 | externally controlled string | | command_injection.py:30:13:30:24 | dict of externally controlled string | command_injection.py:30:13:30:41 | externally controlled string | | command_injection.py:30:13:30:41 | externally controlled string | command_injection.py:32:22:32:26 | externally controlled string | +| command_injection.py:30:13:30:41 | externally controlled string | command_injection.py:32:22:32:26 | externally controlled string | +| command_injection.py:32:22:32:26 | externally controlled string | command_injection.py:32:14:32:26 | externally controlled string | | command_injection.py:32:22:32:26 | externally controlled string | command_injection.py:32:14:32:26 | externally controlled string | #select | command_injection.py:12:15:12:27 | BinaryExpr | command_injection.py:10:13:10:24 | dict of externally controlled string | command_injection.py:12:15:12:27 | externally controlled string | This command depends on $@. | command_injection.py:10:13:10:24 | Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected b/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected index d23198b92a7..46236de24ed 100644 --- a/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected +++ b/python/ql/test/query-tests/Security/CWE-079/ReflectedXss.expected @@ -1,8 +1,13 @@ edges | ../lib/flask/__init__.py:14:19:14:20 | externally controlled string | ../lib/flask/__init__.py:16:25:16:26 | externally controlled string | +| ../lib/flask/__init__.py:14:19:14:20 | externally controlled string | ../lib/flask/__init__.py:16:25:16:26 | externally controlled string | +| reflected_xss.py:7:18:7:29 | dict of externally controlled string | reflected_xss.py:7:18:7:45 | externally controlled string | | reflected_xss.py:7:18:7:29 | dict of externally controlled string | reflected_xss.py:7:18:7:45 | externally controlled string | | reflected_xss.py:7:18:7:45 | externally controlled string | reflected_xss.py:8:44:8:53 | externally controlled string | +| reflected_xss.py:7:18:7:45 | externally controlled string | reflected_xss.py:8:44:8:53 | externally controlled string | | reflected_xss.py:8:26:8:53 | externally controlled string | ../lib/flask/__init__.py:14:19:14:20 | externally controlled string | +| reflected_xss.py:8:26:8:53 | externally controlled string | ../lib/flask/__init__.py:14:19:14:20 | externally controlled string | +| reflected_xss.py:8:44:8:53 | externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string | | reflected_xss.py:8:44:8:53 | externally controlled string | reflected_xss.py:8:26:8:53 | externally controlled string | #select | ../lib/flask/__init__.py:16:25:16:26 | rv | reflected_xss.py:7:18:7:29 | dict of externally controlled string | ../lib/flask/__init__.py:16:25:16:26 | externally controlled string | Cross-site scripting vulnerability due to $@. | reflected_xss.py:7:18:7:29 | Attribute | user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 9c00ffdb2db..c137359a683 100644 --- a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -1,17 +1,22 @@ edges -| sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:12:16:12:22 | django.request.HttpRequest | -| sql_injection.py:12:16:12:22 | django.request.HttpRequest | sql_injection.py:12:16:12:27 | django.http.request.QueryDict | -| sql_injection.py:12:16:12:27 | django.http.request.QueryDict | sql_injection.py:12:16:12:39 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:19:63:19:66 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:22:88:22:91 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:23:76:23:79 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:24:78:24:81 | externally controlled string | -| sql_injection.py:19:63:19:66 | externally controlled string | sql_injection.py:19:13:19:66 | externally controlled string | -| sql_injection.py:22:88:22:91 | externally controlled string | sql_injection.py:22:38:22:91 | externally controlled string | -| sql_injection.py:23:76:23:79 | externally controlled string | sql_injection.py:23:26:23:79 | externally controlled string | -| sql_injection.py:24:78:24:81 | externally controlled string | sql_injection.py:24:28:24:81 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:70:19:77 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:70:19:77 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:88:22:95 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:88:22:95 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:76:23:83 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:76:23:83 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:78:24:85 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:78:24:85 | externally controlled string | +| sql_injection.py:19:70:19:77 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | +| sql_injection.py:19:70:19:77 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | +| sql_injection.py:22:88:22:95 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | +| sql_injection.py:22:88:22:95 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | +| sql_injection.py:23:76:23:83 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | +| sql_injection.py:23:76:23:83 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | +| sql_injection.py:24:78:24:85 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | +| sql_injection.py:24:78:24:85 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | #select -| sql_injection.py:19:13:19:66 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:19:13:19:66 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:22:38:22:91 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:22:38:22:91 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:23:26:23:79 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:23:26:23:79 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:24:28:24:81 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:24:28:24:81 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | +| sql_injection.py:19:24:19:77 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:22:38:22:95 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:23:26:23:83 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:24:28:24:85 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py index b312241b809..9ccca7503bd 100644 --- a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py +++ b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py @@ -1,28 +1,40 @@ +"""This is copied from ql/python/ql/test/library-tests/web/django/test.py +and a only a slight extension of ql/python/ql/src/Security/CWE-089/examples/sql_injection.py +""" -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection, models from django.db.models.expressions import RawSQL -class Name(models.Model): +class User(models.Model): pass -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) -urlpatterns = patterns(url(r'^save_name/$', - save_name, name='save_name')) + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] diff --git a/python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected b/python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected index e01d6b651e3..17430312cf6 100644 --- a/python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-094/CodeInjection.expected @@ -1,8 +1,13 @@ edges | code_injection.py:4:20:4:26 | django.request.HttpRequest | code_injection.py:6:22:6:28 | django.request.HttpRequest | +| code_injection.py:4:20:4:26 | django.request.HttpRequest | code_injection.py:6:22:6:28 | django.request.HttpRequest | +| code_injection.py:6:22:6:28 | django.request.HttpRequest | code_injection.py:6:22:6:33 | django.http.request.QueryDict | | code_injection.py:6:22:6:28 | django.request.HttpRequest | code_injection.py:6:22:6:33 | django.http.request.QueryDict | | code_injection.py:6:22:6:33 | django.http.request.QueryDict | code_injection.py:6:22:6:55 | externally controlled string | +| code_injection.py:6:22:6:33 | django.http.request.QueryDict | code_injection.py:6:22:6:55 | externally controlled string | | code_injection.py:6:22:6:55 | externally controlled string | code_injection.py:7:34:7:43 | externally controlled string | +| code_injection.py:6:22:6:55 | externally controlled string | code_injection.py:7:34:7:43 | externally controlled string | +| code_injection.py:7:34:7:43 | externally controlled string | code_injection.py:7:14:7:44 | externally controlled string | | code_injection.py:7:34:7:43 | externally controlled string | code_injection.py:7:14:7:44 | externally controlled string | #select | code_injection.py:7:14:7:44 | Attribute() | code_injection.py:4:20:4:26 | django.request.HttpRequest | code_injection.py:7:14:7:44 | externally controlled string | $@ flows to here and is interpreted as code. | code_injection.py:4:20:4:26 | request | User-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected b/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected index c714bd52fa5..8bf682bf052 100644 --- a/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected +++ b/python/ql/test/query-tests/Security/CWE-209/StackTraceExposure.expected @@ -1,5 +1,7 @@ edges | test.py:33:15:33:36 | exception info | test.py:34:29:34:31 | exception info | +| test.py:33:15:33:36 | exception info | test.py:34:29:34:31 | exception info | +| test.py:34:29:34:31 | exception info | test.py:34:16:34:32 | exception info | | test.py:34:29:34:31 | exception info | test.py:34:16:34:32 | exception info | #select | test.py:16:16:16:37 | Attribute() | test.py:16:16:16:37 | exception info | test.py:16:16:16:37 | exception info | $@ may be exposed to an external user | test.py:16:16:16:37 | Attribute() | Error information | diff --git a/python/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index cb6106aa395..7681eb91319 100644 --- a/python/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/python/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -1,5 +1,8 @@ edges +| password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password | | test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password | +| test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password | +| test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key | #select | test.py:8:35:8:42 | password | test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password | Sensitive data returned by $@ is logged here. | test.py:7:16:7:29 | get_password() | a call returning a password | | test.py:14:30:14:39 | get_cert() | test.py:14:30:14:39 | a certificate or key | test.py:14:30:14:39 | a certificate or key | Sensitive data returned by $@ is logged here. | test.py:14:30:14:39 | get_cert() | a call returning a certificate or key | diff --git a/python/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected index 23459c0980e..75bedd7187e 100644 --- a/python/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected +++ b/python/ql/test/query-tests/Security/CWE-312/CleartextStorage.expected @@ -1,5 +1,8 @@ edges | password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password | +| password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password | +| test.py:7:16:7:29 | a password | test.py:8:35:8:42 | a password | +| test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key | | test.py:20:12:20:21 | a certificate or key | test.py:22:20:22:23 | a certificate or key | #select | password_in_cookie.py:9:33:9:40 | password | password_in_cookie.py:7:16:7:43 | a password | password_in_cookie.py:9:33:9:40 | a password | Sensitive data from $@ is stored here. | password_in_cookie.py:7:16:7:43 | Attribute() | a request parameter containing a password | diff --git a/python/ql/test/query-tests/Security/CWE-327/TestNode.expected b/python/ql/test/query-tests/Security/CWE-327/TestNode.expected index f49293eddec..c79f7a9d195 100644 --- a/python/ql/test/query-tests/Security/CWE-327/TestNode.expected +++ b/python/ql/test/query-tests/Security/CWE-327/TestNode.expected @@ -5,3 +5,8 @@ | Taint cryptography.encryptor.RC4 | test_cryptography.py:7:17:7:34 | test_cryptography.py:7 | test_cryptography.py:7:17:7:34 | Attribute() | | | Taint cryptography.encryptor.RC4 | test_cryptography.py:8:12:8:20 | test_cryptography.py:8 | test_cryptography.py:8:12:8:20 | encryptor | | | Taint cryptography.encryptor.RC4 | test_cryptography.py:8:42:8:50 | test_cryptography.py:8 | test_cryptography.py:8:42:8:50 | encryptor | | +| Taint sensitive.data.password | test_cryptography.py:5:17:5:30 | test_cryptography.py:5 | test_cryptography.py:5:17:5:30 | get_password() | | +| Taint sensitive.data.password | test_cryptography.py:8:29:8:37 | test_cryptography.py:8 | test_cryptography.py:8:29:8:37 | dangerous | | +| Taint sensitive.data.password | test_cryptography.py:8:42:8:50 | test_cryptography.py:8 | test_cryptography.py:8:42:8:50 | encryptor | | +| Taint sensitive.data.password | test_pycrypto.py:5:17:5:30 | test_pycrypto.py:5 | test_pycrypto.py:5:17:5:30 | get_password() | | +| Taint sensitive.data.password | test_pycrypto.py:7:27:7:35 | test_pycrypto.py:7 | test_pycrypto.py:7:27:7:35 | dangerous | | diff --git a/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected b/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected index af91773ca1d..29618f5dd68 100644 --- a/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected +++ b/python/ql/test/query-tests/Security/CWE-502/UnsafeDeserialization.expected @@ -1,8 +1,13 @@ edges | test.py:11:15:11:26 | dict of externally controlled string | test.py:11:15:11:41 | externally controlled string | +| test.py:11:15:11:26 | dict of externally controlled string | test.py:11:15:11:41 | externally controlled string | +| test.py:11:15:11:41 | externally controlled string | test.py:12:18:12:24 | externally controlled string | | test.py:11:15:11:41 | externally controlled string | test.py:12:18:12:24 | externally controlled string | | test.py:11:15:11:41 | externally controlled string | test.py:13:15:13:21 | externally controlled string | +| test.py:11:15:11:41 | externally controlled string | test.py:13:15:13:21 | externally controlled string | | test.py:11:15:11:41 | externally controlled string | test.py:14:19:14:25 | externally controlled string | +| test.py:11:15:11:41 | externally controlled string | test.py:14:19:14:25 | externally controlled string | +| test.py:11:15:11:41 | externally controlled string | test.py:16:16:16:22 | externally controlled string | | test.py:11:15:11:41 | externally controlled string | test.py:16:16:16:22 | externally controlled string | #select | test.py:12:18:12:24 | payload | test.py:11:15:11:26 | dict of externally controlled string | test.py:12:18:12:24 | externally controlled string | Deserializing of $@. | test.py:11:15:11:26 | Attribute | untrusted input | diff --git a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected index 94f878414da..b9deb72bd40 100644 --- a/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected +++ b/python/ql/test/query-tests/Security/CWE-601/UrlRedirect.expected @@ -1,5 +1,7 @@ edges | test.py:7:22:7:33 | dict of externally controlled string | test.py:7:22:7:51 | externally controlled string | +| test.py:7:22:7:33 | dict of externally controlled string | test.py:7:22:7:51 | externally controlled string | +| test.py:7:22:7:51 | externally controlled string | test.py:8:21:8:26 | externally controlled string | | test.py:7:22:7:51 | externally controlled string | test.py:8:21:8:26 | externally controlled string | #select | test.py:8:21:8:26 | target | test.py:7:22:7:33 | dict of externally controlled string | test.py:8:21:8:26 | externally controlled string | Untrusted URL redirection due to $@. | test.py:7:22:7:33 | Attribute | a user-provided value | diff --git a/python/ql/test/query-tests/Security/lib/django/conf/urls.py b/python/ql/test/query-tests/Security/lib/django/conf/urls.py index cf65525e893..6c1a83baf0b 100644 --- a/python/ql/test/query-tests/Security/lib/django/conf/urls.py +++ b/python/ql/test/query-tests/Security/lib/django/conf/urls.py @@ -1,7 +1,6 @@ - -def url(pattern, *args): +# https://docs.djangoproject.com/en/1.11/_modules/django/conf/urls/#url +def url(regex, view, kwargs=None, name=None): pass def patterns(*urls): pass - diff --git a/python/ql/test/query-tests/Security/lib/django/views/__init__.py b/python/ql/test/query-tests/Security/lib/django/views/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/ql/test/query-tests/Security/lib/django/views/generic.py b/python/ql/test/query-tests/Security/lib/django/views/generic.py new file mode 100644 index 00000000000..d924b03d062 --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/django/views/generic.py @@ -0,0 +1,2 @@ +class View: + pass