Compare commits

..

9 Commits

Author SHA1 Message Date
Esben Sparre Andreasen
96d796579e XXX: add hacky SQL changes for experiments 2020-06-30 09:54:59 +02:00
Esben Sparre Andreasen
246f8755e4 JS: improve CoreKnowledge.qll 2020-06-30 09:54:59 +02:00
Esben Sparre Andreasen
f2e43ad5da JS: add boosted js/sql-injection, js/path-injection, js/xss 2020-06-30 09:54:59 +02:00
Esben Sparre Andreasen
e723c6e790 JS: core improvements 2020-06-25 11:53:42 +02:00
Esben Sparre Andreasen
f60a82dfc3 Merge remote-tracking branch 'origin/master' into HEAD 2020-06-23 12:21:26 +02:00
Henry Mercer
092b0c867e Docs: Fix punctation in section header 2020-06-01 12:15:39 +01:00
Henry Mercer
9ca415f297 Merge pull request #3412 from Z80coder/patch-1
correct "known endpoints" to "candidate endpoints"
2020-05-05 11:25:44 +01:00
Ian Wright
6d02494e61 correct "known endpoints" to "candidate endpoints" 2020-05-05 11:23:32 +01:00
Henry Mercer
15c3820fd9 ATM: Initial commit of ATM for JavaScript beta 2020-05-05 11:15:27 +01:00
1843 changed files with 44687 additions and 89209 deletions

View File

@@ -1,6 +1,5 @@
{ "provide": [ "*/ql/src/qlpack.yml",
"*/ql/test/qlpack.yml",
"*/ql/examples/qlpack.yml",
"*/upgrades/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml" ] }

View File

@@ -2,8 +2,3 @@ name: "CodeQL config"
queries:
- uses: security-and-quality
paths-ignore:
- '/cpp/'
- '/java/'
- '/python/'

View File

@@ -1,3 +0,0 @@
{
"omnisharp.autoStart": false
}

View File

@@ -9,7 +9,7 @@ You can use the [interactive query console](https://lgtm.com/help/lgtm/using-que
## Contributing
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/main/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/github/codeql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
## License

View File

@@ -13,8 +13,6 @@ The following changes in version 1.25 affect C/C++ analysis in all applications.
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Uncontrolled format string (`cpp/tainted-format-string`) | | This query is now displayed by default on LGTM. |
| Uncontrolled format string (through global variable) (`cpp/tainted-format-string-through-global`) | | This query is now displayed by default on LGTM. |
## Changes to libraries

View File

@@ -28,51 +28,27 @@ The following changes in version 1.25 affect C# analysis in all applications.
such as `A<int>.B`, no longer are considered unbound generics. (Such nested types do,
however, still have relevant `.getSourceDeclaration()`s, for example `A<>.B`.)
* The data-flow library has been improved, which affects most security queries by potentially
adding more results:
- Flow through methods now takes nested field reads/writes into account.
For example, the library is able to track flow from `"taint"` to `Sink()` via the method
`GetF2F1()` in
```csharp
class C1
{
string F1;
}
adding more results. Flow through methods now takes nested field reads/writes into account.
For example, the library is able to track flow from `"taint"` to `Sink()` via the method
`GetF2F1()` in
```csharp
class C1
{
string F1;
}
class C2
{
C1 F2;
class C2
{
C1 F2;
string GetF2F1() => F2.F1; // Nested field read
string GetF2F1() => F2.F1; // Nested field read
void M()
{
F2 = new C1() { F1 = "taint" };
Sink(GetF2F1()); // NEW: "taint" reaches here
}
}
```
- Flow through collections is now modeled precisely. For example, instead of modeling an array
store `a[i] = x` as a taint-step from `x` to `a`, we now model it as a data-flow step that
stores `x` into `a`. To get the value back out, a matching read step must be taken.
For source-code based data-flow analysis, the following constructs are modeled as stores into
collections:
- Direct array assignments, `a[i] = x`.
- Array initializers, `new [] { x }`.
- C# 6-style array initializers, `new C() { Array = { [i] = x } }`.
- Call arguments that match a `params` parameter, where the C# compiler creates an array under-the-hood.
- `yield return` statements.
The following source-code constructs read from a collection:
- Direct array reads, `a[i]`.
- `foreach` statements.
For calls out to library code, existing flow summaries have been refined to precisely
capture how they interact with collection contents. For example, a call to
`System.Collections.Generic.List<T>.Add(T)` stores the value of the argument into the
qualifier, and a call to `System.Collections.Generic.List<T>.get_Item(int)` (that is, an
indexer call) reads contents out of the qualifier. Moreover, the effect of
collection-clearing methods such as `System.Collections.Generic.List<T>.Clear()` is now
also modeled.
void M()
{
F2 = new C1() { F1 = "taint" };
Sink(GetF2F1()); // NEW: "taint" reaches here
}
}
```
## Changes to autobuilder

View File

@@ -4,26 +4,20 @@ The following changes in version 1.25 affect Java analysis in all applications.
## General improvements
The Java autobuilder has been improved to detect more Gradle Java versions.
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|------------------------------|------------------------|-----------------------------------|
| Hard-coded credential in API call (`java/hardcoded-credential-api-call`) | More results | The query now recognizes the `BasicAWSCredentials` class of the Amazon client SDK library with hardcoded access key/secret key. |
| Deserialization of user-controlled data (`java/unsafe-deserialization`) | Fewer false positive results | The query no longer reports results using `org.apache.commons.io.serialization.ValidatingObjectInputStream`. |
| Use of a broken or risky cryptographic algorithm (`java/weak-cryptographic-algorithm`) | More results | The query now recognizes the `MessageDigest.getInstance` method. |
| Use of a potentially broken or risky cryptographic algorithm (`java/potentially-weak-cryptographic-algorithm`) | More results | The query now recognizes the `MessageDigest.getInstance` method. |
| Reading from a world writable file (`java/world-writable-file-read`) | More results | The query now recognizes more JDK file operations. |
## Changes to libraries
* The data-flow library has been improved with more taint flow modeling for the
Collections framework and other classes of the JDK. This affects all security
queries using data flow and can yield additional results.
* The data-flow library has been improved with more taint flow modeling for the
Spring framework. This affects all security queries using data flow and can
yield additional results on project that rely on the Spring framework.
* The data-flow library has been improved, which affects most security queries by potentially
adding more results. Flow through methods now takes nested field reads/writes into account.
For example, the library is able to track flow from `"taint"` to `sink()` via the method
@@ -45,5 +39,3 @@ The Java autobuilder has been improved to detect more Gradle Java versions.
}
}
```
* The library has been extended with more support for Java 14 features
(`switch` expressions and pattern-matching for `instanceof`).

View File

@@ -6,34 +6,24 @@
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
- [bluebird](http://bluebirdjs.com/)
- [express](https://www.npmjs.com/package/express)
- [execa](https://www.npmjs.com/package/execa)
- [fancy-log](https://www.npmjs.com/package/fancy-log)
- [fastify](https://www.npmjs.com/package/fastify)
- [foreground-child](https://www.npmjs.com/package/foreground-child)
- [fstream](https://www.npmjs.com/package/fstream)
- [jGrowl](https://github.com/stanlemon/jGrowl)
- [jQuery](https://jquery.com/)
- [marsdb](https://www.npmjs.com/package/marsdb)
- [micro](https://www.npmjs.com/package/micro/)
- [minimongo](https://www.npmjs.com/package/minimongo/)
- [mssql](https://www.npmjs.com/package/mssql)
- [mysql](https://www.npmjs.com/package/mysql)
- [npmlog](https://www.npmjs.com/package/npmlog)
- [opener](https://www.npmjs.com/package/opener)
- [pg](https://www.npmjs.com/package/pg)
- [sequelize](https://www.npmjs.com/package/sequelize)
- [spanner](https://www.npmjs.com/package/spanner)
- [sqlite](https://www.npmjs.com/package/sqlite)
- [ssh2-streams](https://www.npmjs.com/package/ssh2-streams)
- [ssh2](https://www.npmjs.com/package/ssh2)
- [vue](https://www.npmjs.com/package/vue)
- [yargs](https://www.npmjs.com/package/yargs)
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
* TypeScript 3.9 is now supported.
* TypeScript code embedded in HTML and Vue files is now extracted and analyzed.
* The analysis of sanitizers has improved, leading to more accurate
results from the security queries.
@@ -41,17 +31,10 @@
| **Query** | **Tags** | **Purpose** |
|---------------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| DOM text reinterpreted as HTML (`js/xss-through-dom`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities where existing text from the DOM is used as HTML. Results are shown on LGTM by default. |
| Cross-site scripting through DOM (`js/xss-through-dom`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities where existing text from the DOM is used as HTML. Results are not shown on LGTM by default. |
| Incomplete HTML attribute sanitization (`js/incomplete-html-attribute-sanitization`) | security, external/cwe/cwe-20, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities due to incomplete sanitization of HTML meta-characters. Results are shown on LGTM by default. |
| Unsafe expansion of self-closing HTML tag (`js/unsafe-html-expansion`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities caused by unsafe expansion of self-closing HTML tags. |
| Unsafe shell command constructed from library input (`js/shell-command-constructed-from-input`) | correctness, security, external/cwe/cwe-078, external/cwe/cwe-088 | Highlights potential command injections due to a shell command being constructed from library inputs. Results are shown on LGTM by default. |
| Download of sensitive file through insecure connection (`js/insecure-download`) | security, external/cwe/cwe-829 | Highlights downloads of sensitive files through an unencrypted protocol. Results are shown on LGTM by default. |
| Exposure of private files (`js/exposure-of-private-files`) | security, external/cwe/cwe-200 | Highlights servers that serve private files. Results are shown on LGTM by default. |
| Creating biased random numbers from a cryptographically secure source (`js/biased-cryptographic-random`) | security, external/cwe/cwe-327 | Highlights mathematical operations on cryptographically secure numbers that can create biased results. Results are shown on LGTM by default. |
| Storage of sensitive information in build artifact (`js/build-artifact-leak`) | security, external/cwe/cwe-312 | Highlights storage of sensitive information in build artifacts. Results are shown on LGTM by default. |
| Improper code sanitization (`js/bad-code-sanitization`) | security, external/cwe/cwe-094, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights string concatenation where code is constructed without proper sanitization. Results are shown on LGTM by default. |
| Disabling certificate validation (`js/disabling-certificate-validation`) | security, external/cwe-295 | Highlights locations where SSL certificate validation is disabled. Results are shown on LGTM by default. |
| Incomplete multi-character sanitization (`js/incomplete-multi-character-sanitization`) | correctness, security, external/cwe/cwe-20, external/cwe/cwe-116 | Highlights sanitizers that fail to remove dangerous substrings completely. Results are shown on LGTM by default. |
## Changes to existing queries
@@ -60,19 +43,15 @@
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query now recognizes additional safe patterns of constructing HTML. |
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Fewer results | This query now recognizes additional safe patterns of doing URL redirects. |
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
| Exception text reinterpreted as HTML (`js/exception-xss`) | Rephrased and changed visibility | Rephrased name and alert message. Severity lowered from error to warning. Results are now shown on LGTM by default. |
| Expression has no effect (`js/useless-expression`) | Fewer results | This query no longer flags an expression when that expression is the only content of the containing file. |
| Hard-coded credentials (`js/hardcoded-credentials`) | More results | This query now recognizes hard-coded credentials sent via HTTP authorization headers. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
| Insecure randomness (`js/insecure-randomness`) | Fewer results | This query now recognizes when an insecure random value is used as a fallback when secure random values are unsupported. |
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
| Non-linear pattern (`js/non-linear-pattern`) | Fewer duplicates and message changed | This query now generates fewer duplicate alerts and has a clearer explanation in case of type annotations used in a pattern. |
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
| Uncontrolled data used in path expression (`js/path-injection`) | Fewer results | This query no longer flags paths that have been checked to be part of a collection. |
| Unknown directive (`js/unknown-directive`) | Fewer results | This query no longer flags directives generated by the Babel compiler. |
| Unneeded defensive code (`js/unneeded-defensive-code`) | Fewer false-positive results | This query now recognizes checks meant to handle the `document.all` object. |
| Unused property (`js/unused-property`) | Fewer results | This query no longer flags properties of objects that are operands of `yield` expressions. |
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
@@ -108,4 +87,3 @@ The following low-precision queries are no longer run by default on LGTM (their
- `ParameterNode.asExpr()` and `.getAstNode()` now gets the parameter's AST node, whereas previously it had no result.
- `Expr.flow()` now has a more meaningful result for destructuring patterns. Previously this node was disconnected from the data flow graph. Now it represents the values being destructured by the pattern.
* The global data-flow and taint-tracking libraries now model indirect parameter accesses through the `arguments` object in some cases, which may lead to additional results from some of the security queries, particularly "Prototype pollution in utility function".
* The predicates `Type.getProperty()` and variants of `Type.getMethod()` have been deprecated due to lack of use-cases. Looking up a named property of a static type is no longer supported, favoring faster extraction times instead.

View File

@@ -1,9 +1,22 @@
# Improvements to Python analysis
The following changes in version 1.25 affect Python analysis in all applications.
## General improvements
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
## Changes to libraries
* Importing `semmle.python.web.HttpRequest` will no longer import `UntrustedStringKind` transitively. `UntrustedStringKind` is the most commonly used non-abstract subclass of `ExternalStringKind`. If not imported (by one mean or another), taint-tracking queries that concern `ExternalStringKind` will not produce any results. Please ensure such queries contain an explicit import (`import semmle.python.security.strings.Untrusted`).
* Added model of taint sources for HTTP servers using `http.server`.
* Added taint modeling of routed parameters in Flask.
* Improved modeling of built-in methods on strings for taint tracking.
* Improved classification of test files.
* New class `BoundMethodValue` represents a bound method during runtime.
* The query `py/command-line-injection` now recognizes command execution with the `fabric` and `invoke` Python libraries.

View File

@@ -1,5 +1,5 @@
{
"DataFlow Java/C++/C#/Python": [
"DataFlow Java/C++/C#": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll",
@@ -18,18 +18,15 @@
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
"python/ql/src/experimental/dataflow/internal/DataFlowImpl.qll",
"python/ql/src/experimental/dataflow/internal/DataFlowImpl2.qll"
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll"
],
"DataFlow Java/C++/C#/Python Common": [
"DataFlow Java/C++/C# Common": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
"python/ql/src/experimental/dataflow/internal/DataFlowImplCommon.qll"
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll"
],
"TaintTracking::Configuration Java/C++/C#/Python": [
"TaintTracking::Configuration Java/C++/C#": [
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
@@ -40,15 +37,13 @@
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking4/TaintTrackingImpl.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking5/TaintTrackingImpl.qll",
"java/ql/src/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
"java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
"python/ql/src/experimental/dataflow/internal/tainttracking1/TaintTrackingImpl.qll"
"java/ql/src/semmle/code/java/dataflow/internal/tainttracking2/TaintTrackingImpl.qll"
],
"DataFlow Java/C++/C#/Python Consistency checks": [
"DataFlow Java/C++/C# Consistency checks": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll",
"python/ql/src/experimental/dataflow/internal/DataFlowImplConsistency.qll"
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll"
],
"C++ SubBasicBlocks": [
"cpp/ql/src/semmle/code/cpp/controlflow/SubBasicBlocks.qll",

View File

@@ -1,102 +0,0 @@
#!/usr/bin/env python3
import os
import re
path = os.path
needs_an_re = re.compile(r'^(?!Unary)[AEIOU]') # Name requiring "an" instead of "a".
start_qldoc_re = re.compile(r'^\s*/\*\*') # Start of a QLDoc comment
end_qldoc_re = re.compile(r'\*/\s*$') # End of a QLDoc comment
blank_qldoc_line_re = re.compile(r'^\s*\*\s*$') # A line in a QLDoc comment with only the '*'
instruction_class_re = re.compile(r'^class (?P<name>[A-aa-z0-9]+)Instruction\s') # Declaration of an `Instruction` class
opcode_base_class_re = re.compile(r'^abstract class (?P<name>[A-aa-z0-9]+)Opcode\s') # Declaration of an `Opcode` base class
opcode_class_re = re.compile(r'^ class (?P<name>[A-aa-z0-9]+)\s') # Declaration of an `Opcode` class
script_dir = path.realpath(path.dirname(__file__))
instruction_path = path.realpath(path.join(script_dir, '../cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll'))
opcode_path = path.realpath(path.join(script_dir, '../cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll'))
# Scan `Instruction.qll`, keeping track of the QLDoc comment attached to each declaration of a class
# whose name ends with `Instruction`.
instruction_comments = {}
in_qldoc = False
saw_blank_line_in_qldoc = False
qldoc_lines = []
with open(instruction_path, 'r', encoding='utf-8') as instr:
for line in instr:
if in_qldoc:
if end_qldoc_re.search(line):
qldoc_lines.append(line)
in_qldoc = False
elif blank_qldoc_line_re.search(line):
# We're going to skip any lines after the first blank line, to avoid duplicating all
# of the verbose description.
saw_blank_line_in_qldoc = True
elif not saw_blank_line_in_qldoc:
qldoc_lines.append(line)
else:
if start_qldoc_re.search(line):
# Starting a new QLDoc comment.
saw_blank_line_in_qldoc = False
qldoc_lines.append(line)
if not end_qldoc_re.search(line):
in_qldoc = True
else:
instruction_match = instruction_class_re.search(line)
if instruction_match:
# Found the declaration of an `Instruction` class. Record the QLDoc comments.
instruction_comments[instruction_match.group('name')] = qldoc_lines
qldoc_lines = []
# Scan `Opcode.qll`. Whenever we see the declaration of an `Opcode` class for which we have a
# corresponding `Instruction` class, we'll attach a copy of the `Instruction`'s QLDoc comment.
in_qldoc = False
qldoc_lines = []
output_lines = []
with open(opcode_path, 'r', encoding='utf-8') as opcode:
for line in opcode:
if in_qldoc:
qldoc_lines.append(line)
if end_qldoc_re.search(line):
in_qldoc = False
else:
if start_qldoc_re.search(line):
qldoc_lines.append(line)
if not end_qldoc_re.search(line):
in_qldoc = True
else:
name_without_suffix = None
name = None
indent = ''
opcode_base_match = opcode_base_class_re.search(line)
if opcode_base_match:
name_without_suffix = opcode_base_match.group('name')
name = name_without_suffix + 'Opcode'
else:
opcode_match = opcode_class_re.search(line)
if opcode_match:
name_without_suffix = opcode_match.group('name')
name = name_without_suffix
# Indent by two additional spaces, since opcodes are declared in the
# `Opcode` module.
indent = ' '
if name_without_suffix:
# Found an `Opcode` that matches a known `Instruction`. Replace the QLDoc with
# a copy of the one from the `Instruction`.
if instruction_comments.get(name_without_suffix):
article = 'an' if needs_an_re.search(name_without_suffix) else 'a'
qldoc_lines = [
indent + '/**\n',
indent + ' * The `Opcode` for ' + article + ' `' + name_without_suffix + 'Instruction`.\n',
indent + ' *\n',
indent + ' * See the `' + name_without_suffix + 'Instruction` documentation for more details.\n',
indent + ' */\n'
]
output_lines.extend(qldoc_lines)
qldoc_lines = []
output_lines.append(line)
# Write out the updated `Opcode.qll`
with open(opcode_path, 'w', encoding='utf-8') as opcode:
opcode.writelines(output_lines)

View File

@@ -1,13 +0,0 @@
obj/
TestResults/
*.manifest
*.pdb
*.suo
*.mdb
*.vsmdi
csharp.log
**/bin/Debug
**/bin/Release
*.tlog
.vs
*.user

View File

@@ -1,296 +0,0 @@
using Xunit;
using Semmle.Autobuild.Shared;
using System.Collections.Generic;
using System;
using System.Linq;
using Microsoft.Build.Construction;
using System.Xml;
namespace Semmle.Autobuild.Cpp.Tests
{
/// <summary>
/// Test class to script Autobuilder scenarios.
/// For most methods, it uses two fields:
/// - an IList to capture the the arguments passed to it
/// - an IDictionary of possible return values.
/// </summary>
class TestActions : IBuildActions
{
/// <summary>
/// List of strings passed to FileDelete.
/// </summary>
public IList<string> FileDeleteIn = new List<string>();
void IBuildActions.FileDelete(string file)
{
FileDeleteIn.Add(file);
}
public IList<string> FileExistsIn = new List<string>();
public IDictionary<string, bool> FileExists = new Dictionary<string, bool>();
bool IBuildActions.FileExists(string file)
{
FileExistsIn.Add(file);
if (FileExists.TryGetValue(file, out var ret))
return ret;
if (FileExists.TryGetValue(System.IO.Path.GetFileName(file), out ret))
return ret;
throw new ArgumentException("Missing FileExists " + file);
}
public IList<string> RunProcessIn = new List<string>();
public IDictionary<string, int> RunProcess = new Dictionary<string, int>();
public IDictionary<string, string> RunProcessOut = new Dictionary<string, string>();
public IDictionary<string, string> RunProcessWorkingDirectory = new Dictionary<string, string>();
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? env, out IList<string> stdOut)
{
var pattern = cmd + " " + args;
RunProcessIn.Add(pattern);
if (RunProcessOut.TryGetValue(pattern, out var str))
stdOut = str.Split("\n");
else
throw new ArgumentException("Missing RunProcessOut " + pattern);
RunProcessWorkingDirectory.TryGetValue(pattern, out var wd);
if (wd != workingDirectory)
throw new ArgumentException("Missing RunProcessWorkingDirectory " + pattern);
if (RunProcess.TryGetValue(pattern, out var ret))
return ret;
throw new ArgumentException("Missing RunProcess " + pattern);
}
int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary<string, string>? env)
{
var pattern = cmd + " " + args;
RunProcessIn.Add(pattern);
RunProcessWorkingDirectory.TryGetValue(pattern, out var wd);
if (wd != workingDirectory)
throw new ArgumentException("Missing RunProcessWorkingDirectory " + pattern);
if (RunProcess.TryGetValue(pattern, out var ret))
return ret;
throw new ArgumentException("Missing RunProcess " + pattern);
}
public IList<string> DirectoryDeleteIn = new List<string>();
void IBuildActions.DirectoryDelete(string dir, bool recursive)
{
DirectoryDeleteIn.Add(dir);
}
public IDictionary<string, bool> DirectoryExists = new Dictionary<string, bool>();
public IList<string> DirectoryExistsIn = new List<string>();
bool IBuildActions.DirectoryExists(string dir)
{
DirectoryExistsIn.Add(dir);
if (DirectoryExists.TryGetValue(dir, out var ret))
return ret;
throw new ArgumentException("Missing DirectoryExists " + dir);
}
public IDictionary<string, string?> GetEnvironmentVariable = new Dictionary<string, string?>();
string? IBuildActions.GetEnvironmentVariable(string name)
{
if (GetEnvironmentVariable.TryGetValue(name, out var ret))
return ret;
throw new ArgumentException("Missing GetEnvironmentVariable " + name);
}
public string GetCurrentDirectory = "";
string IBuildActions.GetCurrentDirectory()
{
return GetCurrentDirectory;
}
public IDictionary<string, string> EnumerateFiles = new Dictionary<string, string>();
IEnumerable<string> IBuildActions.EnumerateFiles(string dir)
{
if (EnumerateFiles.TryGetValue(dir, out var str))
return str.Split("\n");
throw new ArgumentException("Missing EnumerateFiles " + dir);
}
public IDictionary<string, string> EnumerateDirectories = new Dictionary<string, string>();
IEnumerable<string> IBuildActions.EnumerateDirectories(string dir)
{
if (EnumerateDirectories.TryGetValue(dir, out var str))
return string.IsNullOrEmpty(str) ? Enumerable.Empty<string>() : str.Split("\n");
throw new ArgumentException("Missing EnumerateDirectories " + dir);
}
public bool IsWindows;
bool IBuildActions.IsWindows() => IsWindows;
string IBuildActions.PathCombine(params string[] parts)
{
return string.Join(IsWindows ? '\\' : '/', parts.Where(p => !string.IsNullOrWhiteSpace(p)));
}
string IBuildActions.GetFullPath(string path) => path;
void IBuildActions.WriteAllText(string filename, string contents)
{
}
public IDictionary<string, XmlDocument> LoadXml = new Dictionary<string, XmlDocument>();
XmlDocument IBuildActions.LoadXml(string filename)
{
if (LoadXml.TryGetValue(filename, out var xml))
return xml;
throw new ArgumentException("Missing LoadXml " + filename);
}
public string EnvironmentExpandEnvironmentVariables(string s)
{
foreach (var kvp in GetEnvironmentVariable)
s = s.Replace($"%{kvp.Key}%", kvp.Value);
return s;
}
}
/// <summary>
/// A fake solution to build.
/// </summary>
class TestSolution : ISolution
{
public IEnumerable<SolutionConfigurationInSolution> Configurations => throw new NotImplementedException();
public string DefaultConfigurationName => "Release";
public string DefaultPlatformName => "x86";
public string FullPath { get; set; }
public Version ToolsVersion => new Version("14.0");
public IEnumerable<IProjectOrSolution> IncludedProjects => throw new NotImplementedException();
public TestSolution(string path)
{
FullPath = path;
}
}
public class BuildScriptTests
{
TestActions Actions = new TestActions();
// Records the arguments passed to StartCallback.
IList<string> StartCallbackIn = new List<string>();
void StartCallback(string s, bool silent)
{
StartCallbackIn.Add(s);
}
// Records the arguments passed to EndCallback
IList<string> EndCallbackIn = new List<string>();
IList<int> EndCallbackReturn = new List<int>();
void EndCallback(int ret, string s, bool silent)
{
EndCallbackReturn.Add(ret);
EndCallbackIn.Add(s);
}
CppAutobuilder CreateAutoBuilder(bool isWindows,
string? buildless = null, string? solution = null, string? buildCommand = null, string? ignoreErrors = null,
string? msBuildArguments = null, string? msBuildPlatform = null, string? msBuildConfiguration = null, string? msBuildTarget = null,
string? dotnetArguments = null, string? dotnetVersion = null, string? vsToolsVersion = null,
string? nugetRestore = null, string? allSolutions = null,
string cwd = @"C:\Project")
{
string codeqlUpperLanguage = Language.Cpp.UpperCaseName;
Actions.GetEnvironmentVariable[$"CODEQL_AUTOBUILDER_{codeqlUpperLanguage}_NO_INDEXING"] = "false";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = "";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = "";
Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}";
Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java";
Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa";
Actions.GetEnvironmentVariable["SEMMLE_JAVA_HOME"] = @"C:\odasa\tools\java";
Actions.GetEnvironmentVariable["SEMMLE_PLATFORM_TOOLS"] = @"C:\odasa\tools";
Actions.GetEnvironmentVariable["LGTM_INDEX_VSTOOLS_VERSION"] = vsToolsVersion;
Actions.GetEnvironmentVariable["LGTM_INDEX_MSBUILD_ARGUMENTS"] = msBuildArguments;
Actions.GetEnvironmentVariable["LGTM_INDEX_MSBUILD_PLATFORM"] = msBuildPlatform;
Actions.GetEnvironmentVariable["LGTM_INDEX_MSBUILD_CONFIGURATION"] = msBuildConfiguration;
Actions.GetEnvironmentVariable["LGTM_INDEX_MSBUILD_TARGET"] = msBuildTarget;
Actions.GetEnvironmentVariable["LGTM_INDEX_DOTNET_ARGUMENTS"] = dotnetArguments;
Actions.GetEnvironmentVariable["LGTM_INDEX_DOTNET_VERSION"] = dotnetVersion;
Actions.GetEnvironmentVariable["LGTM_INDEX_BUILD_COMMAND"] = buildCommand;
Actions.GetEnvironmentVariable["LGTM_INDEX_SOLUTION"] = solution;
Actions.GetEnvironmentVariable["LGTM_INDEX_IGNORE_ERRORS"] = ignoreErrors;
Actions.GetEnvironmentVariable["LGTM_INDEX_BUILDLESS"] = buildless;
Actions.GetEnvironmentVariable["LGTM_INDEX_ALL_SOLUTIONS"] = allSolutions;
Actions.GetEnvironmentVariable["LGTM_INDEX_NUGET_RESTORE"] = nugetRestore;
Actions.GetEnvironmentVariable["ProgramFiles(x86)"] = isWindows ? @"C:\Program Files (x86)" : null;
Actions.GetCurrentDirectory = cwd;
Actions.IsWindows = isWindows;
var options = new AutobuildOptions(Actions, Language.Cpp);
return new CppAutobuilder(Actions, options);
}
void TestAutobuilderScript(Autobuilder autobuilder, int expectedOutput, int commandsRun)
{
Assert.Equal(expectedOutput, autobuilder.GetBuildScript().Run(Actions, StartCallback, EndCallback));
// Check expected commands actually ran
Assert.Equal(commandsRun, StartCallbackIn.Count);
Assert.Equal(commandsRun, EndCallbackIn.Count);
Assert.Equal(commandsRun, EndCallbackReturn.Count);
var action = Actions.RunProcess.GetEnumerator();
for (int cmd = 0; cmd < commandsRun; ++cmd)
{
Assert.True(action.MoveNext());
Assert.Equal(action.Current.Key, StartCallbackIn[cmd]);
Assert.Equal(action.Current.Value, EndCallbackReturn[cmd]);
}
}
[Fact]
public void TestDefaultCppAutobuilder()
{
Actions.EnumerateFiles[@"C:\Project"] = "";
Actions.EnumerateDirectories[@"C:\Project"] = "";
var autobuilder = CreateAutoBuilder(true);
var script = autobuilder.GetBuildScript();
// Fails due to no solutions present.
Assert.NotEqual(0, script.Run(Actions, StartCallback, EndCallback));
}
[Fact]
public void TestCppAutobuilderSuccess()
{
Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\csharp\nuget\nuget.exe restore C:\Project\test.sln"] = 1;
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && C:\odasa\tools\odasa index --auto msbuild C:\Project\test.sln /p:UseSharedCompilation=false /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"" /p:MvcBuildViews=true"] = 0;
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = "";
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"] = true;
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"] = true;
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"] = true;
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"] = true;
Actions.FileExists[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"] = true;
Actions.EnumerateFiles[@"C:\Project"] = "foo.cs\ntest.slx";
Actions.EnumerateDirectories[@"C:\Project"] = "";
var autobuilder = CreateAutoBuilder(true);
var solution = new TestSolution(@"C:\Project\test.sln");
autobuilder.ProjectsOrSolutionsToBuild.Add(solution);
TestAutobuilderScript(autobuilder, 0, 2);
}
}
}

View File

@@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.FileSystem" Version="4.3.0" />
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Autobuild.Cpp\Semmle.Autobuild.Cpp.csproj" />
<ProjectReference Include="..\..\..\csharp\autobuilder\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,23 +0,0 @@
using Semmle.Autobuild.Shared;
namespace Semmle.Autobuild.Cpp
{
public class CppAutobuilder : Autobuilder
{
public CppAutobuilder(IBuildActions actions, AutobuildOptions options) : base(actions, options) { }
public override BuildScript GetBuildScript()
{
if (Options.BuildCommand != null)
return new BuildCommandRule((_, f) => f(null)).Analyse(this, false);
return
// First try MSBuild
new MsBuildRule().Analyse(this, true) |
// Then look for a script that might be a build script
(() => new BuildCommandAutoRule((_, f) => f(null)).Analyse(this, true)) |
// All attempts failed: print message
AutobuildFailure();
}
}
}

View File

@@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyName>Semmle.Autobuild.Cpp</AssemblyName>
<RootNamespace>Semmle.Autobuild.Cpp</RootNamespace>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build" Version="16.0.461" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\csharp\extractor\Semmle.Util\Semmle.Util.csproj" />
<ProjectReference Include="..\..\..\csharp\autobuilder\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,3 +0,0 @@
name: codeql-cpp-examples
version: 0.0.0
libraryPathDependencies: codeql-cpp

View File

@@ -15,15 +15,6 @@ import cpp
import semmle.code.cpp.models.implementations.Strcpy
import semmle.code.cpp.dataflow.DataFlow
/**
* A string copy function that returns a string, rather than an error code (for
* example, `strcpy` returns a string, whereas `strcpy_s` returns an error
* code).
*/
class InterestingStrcpyFunction extends StrcpyFunction {
InterestingStrcpyFunction() { getType().getUnspecifiedType() instanceof PointerType }
}
predicate isBoolean(Expr e1) {
exists(Type t1 |
t1 = e1.getType() and
@@ -34,12 +25,12 @@ predicate isBoolean(Expr e1) {
predicate isStringCopyCastedAsBoolean(FunctionCall func, Expr expr1, string msg) {
DataFlow::localExprFlow(func, expr1) and
isBoolean(expr1.getConversion*()) and
func.getTarget() instanceof InterestingStrcpyFunction and
func.getTarget() instanceof StrcpyFunction and
msg = "Return value of " + func.getTarget().getName() + " used as a Boolean."
}
predicate isStringCopyUsedInLogicalOperationOrCondition(FunctionCall func, Expr expr1, string msg) {
func.getTarget() instanceof InterestingStrcpyFunction and
func.getTarget() instanceof StrcpyFunction and
(
(
// it is being used in an equality or logical operation

View File

@@ -5,7 +5,7 @@
* or data representation problems.
* @kind path-problem
* @problem.severity warning
* @precision high
* @precision medium
* @id cpp/tainted-format-string
* @tags reliability
* security

View File

@@ -5,7 +5,7 @@
* or data representation problems.
* @kind path-problem
* @problem.severity warning
* @precision high
* @precision medium
* @id cpp/tainted-format-string-through-global
* @tags reliability
* security

View File

@@ -18,7 +18,7 @@ abstract class InsecureCryptoSpec extends Locatable {
}
Function getAnInsecureFunction() {
result.getName().regexpMatch(getInsecureAlgorithmRegex()) and
result.getName().regexpMatch(algorithmBlacklistRegex()) and
exists(result.getACallToThisFunction())
}
@@ -33,7 +33,7 @@ class InsecureFunctionCall extends InsecureCryptoSpec, FunctionCall {
}
Macro getAnInsecureMacro() {
result.getName().regexpMatch(getInsecureAlgorithmRegex()) and
result.getName().regexpMatch(algorithmBlacklistRegex()) and
exists(result.getAnInvocation())
}

View File

@@ -9,10 +9,3 @@
tags contain:
- ide-contextual-queries/local-definitions
- ide-contextual-queries/local-references
- query: Metrics/Dependencies/ExternalDependencies.ql
- query: Metrics/Dependencies/ExternalDependenciesSourceLinks.ql
- query: Metrics/Files/FLinesOfCode.ql
- query: Metrics/Files/FLinesOfCommentedOutCode.ql
- query: Metrics/Files/FLinesOfComments.ql
- query: Metrics/Files/FLinesOfDuplicatedCode.ql
- query: Metrics/Files/FNumberOfTests.ql

View File

@@ -20,7 +20,7 @@ import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.ValueNumbering
private import semmle.code.cpp.ir.internal.CppType
private import semmle.code.cpp.models.interfaces.Allocation
private import experimental.semmle.code.cpp.rangeanalysis.RangeUtils
private import semmle.code.cpp.rangeanalysis.RangeUtils
private newtype TLength =
TZeroLength() or

View File

@@ -13,7 +13,7 @@
import cpp
private import experimental.semmle.code.cpp.rangeanalysis.ArrayLengthAnalysis
private import experimental.semmle.code.cpp.rangeanalysis.RangeAnalysis
private import semmle.code.cpp.rangeanalysis.RangeAnalysis
/**
* Gets the instruction that computes the address of memory that `i` accesses.

View File

@@ -1,27 +0,0 @@
/**
* @name Print AST
* @description Outputs a representation of a file's Abstract Syntax Tree. This
* query is used by the VS Code extension.
* @id cpp/print-ast
* @kind graph
* @tags ide-contextual-queries/print-ast
*/
import cpp
import semmle.code.cpp.PrintAST
import definitions
/**
* The source file to generate an AST from.
*/
external string selectedSourceFile();
class Cfg extends PrintASTConfiguration {
/**
* Holds if the AST for `func` should be printed.
* Print All functions from the selected file.
*/
override predicate shouldPrintFunction(Function func) {
func.getFile() = getEncodedFile(selectedSourceFile())
}
}

View File

@@ -33,7 +33,7 @@ private import semmle.code.cpp.internal.ResolveClass
class Class extends UserType {
Class() { isClass(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "Class" }
override string getCanonicalQLClass() { result = "Class" }
/** Gets a child declaration of this class, struct or union. */
override Declaration getADeclaration() { result = this.getAMember() }
@@ -768,7 +768,7 @@ class ClassDerivation extends Locatable, @derivation {
*/
Class getBaseClass() { result = getBaseType().getUnderlyingType() }
override string getAPrimaryQlClass() { result = "ClassDerivation" }
override string getCanonicalQLClass() { result = "ClassDerivation" }
/**
* Gets the type from which we are deriving, without resolving any
@@ -849,7 +849,9 @@ class ClassDerivation extends Locatable, @derivation {
class LocalClass extends Class {
LocalClass() { isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalStruct and result = "LocalClass" }
override string getCanonicalQLClass() {
not this instanceof LocalStruct and result = "LocalClass"
}
override Function getEnclosingAccessHolder() { result = this.getEnclosingFunction() }
}
@@ -870,7 +872,7 @@ class LocalClass extends Class {
class NestedClass extends Class {
NestedClass() { this.isMember() }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not this instanceof NestedStruct and result = "NestedClass"
}
@@ -891,7 +893,7 @@ class NestedClass extends Class {
class AbstractClass extends Class {
AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) }
override string getAPrimaryQlClass() { result = "AbstractClass" }
override string getCanonicalQLClass() { result = "AbstractClass" }
}
/**
@@ -932,7 +934,7 @@ class TemplateClass extends Class {
exists(result.getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "TemplateClass" }
override string getCanonicalQLClass() { result = "TemplateClass" }
}
/**
@@ -953,7 +955,7 @@ class ClassTemplateInstantiation extends Class {
ClassTemplateInstantiation() { tc.getAnInstantiation() = this }
override string getAPrimaryQlClass() { result = "ClassTemplateInstantiation" }
override string getCanonicalQLClass() { result = "ClassTemplateInstantiation" }
/**
* Gets the class template from which this instantiation was instantiated.
@@ -994,7 +996,7 @@ abstract class ClassTemplateSpecialization extends Class {
count(int i | exists(result.getTemplateArgument(i)))
}
override string getAPrimaryQlClass() { result = "ClassTemplateSpecialization" }
override string getCanonicalQLClass() { result = "ClassTemplateSpecialization" }
}
/**
@@ -1023,7 +1025,7 @@ class FullClassTemplateSpecialization extends ClassTemplateSpecialization {
not this instanceof ClassTemplateInstantiation
}
override string getAPrimaryQlClass() { result = "FullClassTemplateSpecialization" }
override string getCanonicalQLClass() { result = "FullClassTemplateSpecialization" }
}
/**
@@ -1062,7 +1064,7 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
count(int i | exists(getTemplateArgument(i)))
}
override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" }
override string getCanonicalQLClass() { result = "PartialClassTemplateSpecialization" }
}
/**
@@ -1087,7 +1089,7 @@ deprecated class Interface extends Class {
)
}
override string getAPrimaryQlClass() { result = "Interface" }
override string getCanonicalQLClass() { result = "Interface" }
}
/**
@@ -1102,7 +1104,7 @@ deprecated class Interface extends Class {
class VirtualClassDerivation extends ClassDerivation {
VirtualClassDerivation() { hasSpecifier("virtual") }
override string getAPrimaryQlClass() { result = "VirtualClassDerivation" }
override string getCanonicalQLClass() { result = "VirtualClassDerivation" }
}
/**
@@ -1122,7 +1124,7 @@ class VirtualClassDerivation extends ClassDerivation {
class VirtualBaseClass extends Class {
VirtualBaseClass() { exists(VirtualClassDerivation cd | cd.getBaseClass() = this) }
override string getAPrimaryQlClass() { result = "VirtualBaseClass" }
override string getCanonicalQLClass() { result = "VirtualBaseClass" }
/** A virtual class derivation of which this class/struct is the base. */
VirtualClassDerivation getAVirtualDerivation() { result.getBaseClass() = this }
@@ -1144,7 +1146,7 @@ class VirtualBaseClass extends Class {
class ProxyClass extends UserType {
ProxyClass() { usertypes(underlyingElement(this), _, 9) }
override string getAPrimaryQlClass() { result = "ProxyClass" }
override string getCanonicalQLClass() { result = "ProxyClass" }
/** Gets the location of the proxy class. */
override Location getLocation() { result = getTemplateParameter().getDefinitionLocation() }

View File

@@ -124,7 +124,7 @@ class Declaration extends Locatable, @declaration {
* To test whether this declaration has a particular name in the global
* namespace, use `hasGlobalName`.
*/
string getName() { none() } // overridden in subclasses
abstract string getName();
/** Holds if this declaration has the given name. */
predicate hasName(string name) { name = this.getName() }
@@ -140,7 +140,7 @@ class Declaration extends Locatable, @declaration {
}
/** Gets a specifier of this declaration. */
Specifier getASpecifier() { none() } // overridden in subclasses
abstract Specifier getASpecifier();
/** Holds if this declaration has a specifier with the given name. */
predicate hasSpecifier(string name) { this.getASpecifier().hasName(name) }
@@ -156,7 +156,7 @@ class Declaration extends Locatable, @declaration {
* Gets the location of a declaration entry corresponding to this
* declaration.
*/
Location getADeclarationLocation() { none() } // overridden in subclasses
abstract Location getADeclarationLocation();
/**
* Gets the declaration entry corresponding to this declaration that is a
@@ -165,7 +165,7 @@ class Declaration extends Locatable, @declaration {
DeclarationEntry getDefinition() { none() }
/** Gets the location of the definition, if any. */
Location getDefinitionLocation() { none() } // overridden in subclasses
abstract Location getDefinitionLocation();
/** Holds if the declaration has a definition. */
predicate hasDefinition() { exists(this.getDefinition()) }
@@ -289,8 +289,6 @@ class Declaration extends Locatable, @declaration {
}
}
private class TDeclarationEntry = @var_decl or @type_decl or @fun_decl;
/**
* A C/C++ declaration entry. For example the following code contains five
* declaration entries:
@@ -306,9 +304,9 @@ private class TDeclarationEntry = @var_decl or @type_decl or @fun_decl;
* See the comment above `Declaration` for an explanation of the relationship
* between `Declaration` and `DeclarationEntry`.
*/
class DeclarationEntry extends Locatable, TDeclarationEntry {
abstract class DeclarationEntry extends Locatable {
/** Gets a specifier associated with this declaration entry. */
string getASpecifier() { none() } // overridden in subclasses
abstract string getASpecifier();
/**
* Gets the name associated with the corresponding definition (where
@@ -331,10 +329,10 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
* `I.getADeclarationEntry()` returns `D`
* but `D.getDeclaration()` only returns `C`
*/
Declaration getDeclaration() { none() } // overridden in subclasses
abstract Declaration getDeclaration();
/** Gets the name associated with this declaration entry, if any. */
string getName() { none() } // overridden in subclasses
abstract string getName();
/**
* Gets the type associated with this declaration entry.
@@ -343,7 +341,7 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
* For function declarations, get the return type of the function.
* For type declarations, get the type being declared.
*/
Type getType() { none() } // overridden in subclasses
abstract Type getType();
/**
* Gets the type associated with this declaration entry after specifiers
@@ -361,7 +359,7 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
predicate hasSpecifier(string specifier) { getASpecifier() = specifier }
/** Holds if this declaration entry is a definition. */
predicate isDefinition() { none() } // overridden in subclasses
abstract predicate isDefinition();
override string toString() {
if isDefinition()
@@ -373,8 +371,6 @@ class DeclarationEntry extends Locatable, TDeclarationEntry {
}
}
private class TAccessHolder = @function or @usertype;
/**
* A declaration that can potentially have more C++ access rights than its
* enclosing element. This comprises `Class` (they have access to their own
@@ -396,7 +392,7 @@ private class TAccessHolder = @function or @usertype;
* the informal phrase "_R_ occurs in a member or friend of class C", where
* `AccessHolder` corresponds to this _R_.
*/
class AccessHolder extends Declaration, TAccessHolder {
abstract class AccessHolder extends Declaration {
/**
* Holds if `this` can access private members of class `c`.
*
@@ -414,7 +410,7 @@ class AccessHolder extends Declaration, TAccessHolder {
/**
* Gets the nearest enclosing `AccessHolder`.
*/
AccessHolder getEnclosingAccessHolder() { none() } // overridden in subclasses
abstract AccessHolder getEnclosingAccessHolder();
/**
* Holds if a base class `base` of `derived` _is accessible at_ `this` (N4140

View File

@@ -55,21 +55,12 @@ class ElementBase extends @element {
cached
string toString() { none() }
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
/**
* Gets the name of a primary CodeQL class to which this element belongs.
* Canonical QL class corresponding to this element.
*
* For most elements, this is simply the most precise syntactic category to
* which they belong; for example, `AddExpr` is a primary class, but
* `BinaryOperation` is not.
*
* This predicate always has a result. If no primary class can be
* determined, the result is `"???"`. If multiple primary classes match,
* this predicate can have multiple results.
* ElementBase is the root class for this predicate.
*/
string getAPrimaryQlClass() { result = "???" }
string getCanonicalQLClass() { result = "???" }
}
/**
@@ -197,8 +188,7 @@ class Element extends ElementBase {
initialisers(underlyingElement(this), unresolveElement(result), _, _) or
exprconv(unresolveElement(result), underlyingElement(this)) or
param_decl_bind(underlyingElement(this), _, unresolveElement(result)) or
using_container(unresolveElement(result), underlyingElement(this)) or
static_asserts(unresolveElement(this), _, _, _, underlyingElement(result))
using_container(unresolveElement(result), underlyingElement(this))
}
/** Gets the closest `Element` enclosing this one. */
@@ -279,12 +269,12 @@ class StaticAssert extends Locatable, @static_assert {
/**
* Gets the expression which this static assertion ensures is true.
*/
Expr getCondition() { static_asserts(underlyingElement(this), unresolveElement(result), _, _, _) }
Expr getCondition() { static_asserts(underlyingElement(this), unresolveElement(result), _, _) }
/**
* Gets the message which will be reported by the compiler if this static assertion fails.
*/
string getMessage() { static_asserts(underlyingElement(this), _, result, _, _) }
string getMessage() { static_asserts(underlyingElement(this), _, result, _) }
override Location getLocation() { static_asserts(underlyingElement(this), _, _, result, _) }
override Location getLocation() { static_asserts(underlyingElement(this), _, _, result) }
}

View File

@@ -38,7 +38,7 @@ class Enum extends UserType, IntegralOrEnumType {
enumconstants(unresolveElement(result), underlyingElement(this), index, _, _, _)
}
override string getAPrimaryQlClass() { result = "Enum" }
override string getCanonicalQLClass() { result = "Enum" }
/**
* Gets a descriptive string for the enum. This method is only intended to
@@ -87,7 +87,7 @@ class Enum extends UserType, IntegralOrEnumType {
class LocalEnum extends Enum {
LocalEnum() { isLocal() }
override string getAPrimaryQlClass() { result = "LocalEnum" }
override string getCanonicalQLClass() { result = "LocalEnum" }
}
/**
@@ -105,7 +105,7 @@ class LocalEnum extends Enum {
class NestedEnum extends Enum {
NestedEnum() { this.isMember() }
override string getAPrimaryQlClass() { result = "NestedEnum" }
override string getCanonicalQLClass() { result = "NestedEnum" }
/** Holds if this member is private. */
predicate isPrivate() { this.hasSpecifier("private") }
@@ -130,7 +130,7 @@ class NestedEnum extends Enum {
class ScopedEnum extends Enum {
ScopedEnum() { usertypes(underlyingElement(this), _, 13) }
override string getAPrimaryQlClass() { result = "ScopedEnum" }
override string getCanonicalQLClass() { result = "ScopedEnum" }
}
/**
@@ -153,7 +153,7 @@ class EnumConstant extends Declaration, @enumconstant {
enumconstants(underlyingElement(this), unresolveElement(result), _, _, _, _)
}
override string getAPrimaryQlClass() { result = "EnumConstant" }
override string getCanonicalQLClass() { result = "EnumConstant" }
override Class getDeclaringType() { result = this.getDeclaringEnum().getDeclaringType() }

View File

@@ -23,7 +23,7 @@ import semmle.code.cpp.exprs.Access
class Field extends MemberVariable {
Field() { fieldoffsets(underlyingElement(this), _, _) }
override string getAPrimaryQlClass() { result = "Field" }
override string getCanonicalQLClass() { result = "Field" }
/**
* Gets the offset of this field in bytes from the start of its declaring
@@ -90,7 +90,7 @@ class Field extends MemberVariable {
class BitField extends Field {
BitField() { bitfield(underlyingElement(this), _, _) }
override string getAPrimaryQlClass() { result = "BitField" }
override string getCanonicalQLClass() { result = "BitField" }
/**
* Gets the size of this bitfield in bits (on the machine where facts

View File

@@ -178,7 +178,7 @@ class Folder extends Container, @folder {
result.hasLocationInfo(_, 0, 0, 0, 0)
}
override string getAPrimaryQlClass() { result = "Folder" }
override string getCanonicalQLClass() { result = "Folder" }
/**
* DEPRECATED: Use `getLocation` instead.
@@ -246,7 +246,7 @@ class File extends Container, @file {
override string toString() { result = Container.super.toString() }
override string getAPrimaryQlClass() { result = "File" }
override string getCanonicalQLClass() { result = "File" }
override Location getLocation() {
result.getContainer() = this and
@@ -382,7 +382,7 @@ class HeaderFile extends File {
exists(Include i | i.getIncludedFile() = this)
}
override string getAPrimaryQlClass() { result = "HeaderFile" }
override string getCanonicalQLClass() { result = "HeaderFile" }
/**
* Holds if this header file does not contain any declaration entries or top level
@@ -408,7 +408,7 @@ class HeaderFile extends File {
class CFile extends File {
CFile() { exists(string ext | ext = this.getExtension().toLowerCase() | ext = "c" or ext = "i") }
override string getAPrimaryQlClass() { result = "CFile" }
override string getCanonicalQLClass() { result = "CFile" }
}
/**
@@ -436,7 +436,7 @@ class CppFile extends File {
)
}
override string getAPrimaryQlClass() { result = "CppFile" }
override string getCanonicalQLClass() { result = "CppFile" }
}
/**

View File

@@ -27,7 +27,7 @@ class FriendDecl extends Declaration, @frienddecl {
*/
override Location getADeclarationLocation() { result = this.getLocation() }
override string getAPrimaryQlClass() { result = "FriendDecl" }
override string getCanonicalQLClass() { result = "FriendDecl" }
/**
* Implements the abstract method `Declaration.getDefinitionLocation`. A

View File

@@ -3,6 +3,7 @@
*/
import semmle.code.cpp.Location
import semmle.code.cpp.Member
import semmle.code.cpp.Class
import semmle.code.cpp.Parameter
import semmle.code.cpp.exprs.Call
@@ -513,7 +514,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
/** Gets the function which is being declared or defined. */
override Function getDeclaration() { result = getFunction() }
override string getAPrimaryQlClass() { result = "FunctionDeclarationEntry" }
override string getCanonicalQLClass() { result = "FunctionDeclarationEntry" }
/** Gets the function which is being declared or defined. */
Function getFunction() { fun_decls(underlyingElement(this), unresolveElement(result), _, _, _) }
@@ -698,7 +699,7 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
class TopLevelFunction extends Function {
TopLevelFunction() { not this.isMember() }
override string getAPrimaryQlClass() { result = "TopLevelFunction" }
override string getCanonicalQLClass() { result = "TopLevelFunction" }
}
/**
@@ -707,7 +708,7 @@ class TopLevelFunction extends Function {
class Operator extends Function {
Operator() { functions(underlyingElement(this), _, 5) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not this instanceof MemberFunction and result = "Operator"
}
}
@@ -738,7 +739,7 @@ class TemplateFunction extends Function {
is_function_template(underlyingElement(this)) and exists(getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "TemplateFunction" }
override string getCanonicalQLClass() { result = "TemplateFunction" }
/**
* Gets a compiler-generated instantiation of this function template.
@@ -778,7 +779,7 @@ class FunctionTemplateInstantiation extends Function {
FunctionTemplateInstantiation() { tf.getAnInstantiation() = this }
override string getAPrimaryQlClass() { result = "FunctionTemplateInstantiation" }
override string getCanonicalQLClass() { result = "FunctionTemplateInstantiation" }
/**
* Gets the function template from which this instantiation was instantiated.
@@ -823,7 +824,7 @@ class FunctionTemplateInstantiation extends Function {
class FunctionTemplateSpecialization extends Function {
FunctionTemplateSpecialization() { this.isSpecialization() }
override string getAPrimaryQlClass() { result = "FunctionTemplateSpecialization" }
override string getCanonicalQLClass() { result = "FunctionTemplateSpecialization" }
/**
* Gets the primary template for the specialization (the function template

View File

@@ -1,7 +1,3 @@
/**
* Provides the `Initializer` class, representing C/C++ declaration initializers.
*/
import semmle.code.cpp.controlflow.ControlFlowGraph
/**
@@ -22,7 +18,7 @@ import semmle.code.cpp.controlflow.ControlFlowGraph
class Initializer extends ControlFlowNode, @initialiser {
override Location getLocation() { initialisers(underlyingElement(this), _, _, result) }
override string getAPrimaryQlClass() { result = "Initializer" }
override string getCanonicalQLClass() { result = "Initializer" }
/** Holds if this initializer is explicit in the source. */
override predicate fromSource() { not this.getLocation() instanceof UnknownLocation }

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for loop iteration variables.
*/
import semmle.code.cpp.Variable
/**
@@ -11,18 +7,14 @@ import semmle.code.cpp.Variable
class LoopCounter extends Variable {
LoopCounter() { exists(ForStmt f | f.getAnIterationVariable() = this) }
/**
* Gets an access of this variable within loop `f`.
*/
// Gets an access of this variable within loop `f`.
VariableAccess getVariableAccessInLoop(ForStmt f) {
this.getALoop() = f and
result.getEnclosingStmt().getParent*() = f and
this = result.getTarget()
}
/**
* Gets a loop which uses this variable as its counter.
*/
// Gets a loop which uses this variable as its counter.
ForStmt getALoop() { result.getAnIterationVariable() = this }
}
@@ -33,18 +25,14 @@ class LoopCounter extends Variable {
class LoopControlVariable extends Variable {
LoopControlVariable() { this = loopControlVariable(_) }
/**
* Gets an access of this variable within loop `f`.
*/
// Gets an access of this variable within loop `f`.
VariableAccess getVariableAccessInLoop(ForStmt f) {
this.getALoop() = f and
result.getEnclosingStmt().getParent*() = f and
this = result.getTarget()
}
/**
* Gets a loop which uses this variable as its control variable.
*/
// Gets a loop which uses this variable as its control variable.
ForStmt getALoop() { this = loopControlVariable(result) }
}

View File

@@ -1,7 +1,3 @@
/**
* Proivdes the `LinkTarget` class representing linker invocations during the build process.
*/
import semmle.code.cpp.Class
import semmle.code.cpp.File
import semmle.code.cpp.Function

View File

@@ -1,7 +1,3 @@
/**
* Provides classes and predicates for locations in the source code.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.File
@@ -15,16 +11,16 @@ class Location extends @location {
/** Gets the file corresponding to this location, if any. */
File getFile() { result = this.getContainer() }
/** Gets the 1-based line number (inclusive) where this location starts. */
/** Gets the start line of this location. */
int getStartLine() { this.fullLocationInfo(_, result, _, _, _) }
/** Gets the 1-based column number (inclusive) where this location starts. */
/** Gets the start column of this location. */
int getStartColumn() { this.fullLocationInfo(_, _, result, _, _) }
/** Gets the 1-based line number (inclusive) where this location ends. */
/** Gets the end line of this location. */
int getEndLine() { this.fullLocationInfo(_, _, _, result, _) }
/** Gets the 1-based column number (inclusive) where this location ends. */
/** Gets the end column of this location. */
int getEndColumn() { this.fullLocationInfo(_, _, _, _, result) }
/**

View File

@@ -13,7 +13,7 @@ class Macro extends PreprocessorDirective, @ppd_define {
*/
override string getHead() { preproctext(underlyingElement(this), result, _) }
override string getAPrimaryQlClass() { result = "Macro" }
override string getCanonicalQLClass() { result = "Macro" }
/**
* Gets the body of this macro. For example, `(((x)>(y))?(x):(y))` in
@@ -74,7 +74,7 @@ class MacroAccess extends Locatable, @macroinvocation {
*/
override Location getLocation() { result = this.getOutermostMacroAccess().getActualLocation() }
override string getAPrimaryQlClass() { result = "MacroAccess" }
override string getCanonicalQLClass() { result = "MacroAccess" }
/**
* Gets the location of this macro access. For a nested access, where
@@ -147,7 +147,7 @@ class MacroAccess extends Locatable, @macroinvocation {
class MacroInvocation extends MacroAccess {
MacroInvocation() { macroinvocations(underlyingElement(this), _, _, 1) }
override string getAPrimaryQlClass() { result = "MacroInvocation" }
override string getCanonicalQLClass() { result = "MacroInvocation" }
/**
* Gets an element that occurs in this macro invocation or a nested macro
@@ -179,11 +179,6 @@ class MacroInvocation extends MacroAccess {
result.(Stmt).getGeneratingMacro() = this
}
/**
* Gets a function that includes an expression that is affected by this macro
* invocation. If the macro expansion includes the end of one function and
* the beginning of another, this predicate will get both.
*/
Function getEnclosingFunction() {
result = this.getAnAffectedElement().(Expr).getEnclosingFunction()
}

View File

@@ -1,6 +1,2 @@
/**
* DEPRECATED: import `semmle.code.cpp.Element` and/or `semmle.code.cpp.Type` directly as required.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Type

View File

@@ -25,7 +25,7 @@ import cpp
class MemberFunction extends Function {
MemberFunction() { this.isMember() }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not this instanceof CopyAssignmentOperator and
not this instanceof MoveAssignmentOperator and
result = "MemberFunction"
@@ -70,14 +70,6 @@ class MemberFunction extends Function {
result = getADeclarationEntry() and result != getDefinition()
)
}
/**
* Gets the type of the `this` parameter associated with this member function, if any. The type
* may have `const` and/or `volatile` qualifiers, matching the function declaration.
*/
PointerType getTypeOfThis() {
member_function_this_type(underlyingElement(this), unresolveElement(result))
}
}
/**
@@ -101,7 +93,7 @@ class MemberFunction extends Function {
class VirtualFunction extends MemberFunction {
VirtualFunction() { this.hasSpecifier("virtual") or purefunctions(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "VirtualFunction" }
override string getCanonicalQLClass() { result = "VirtualFunction" }
/** Holds if this virtual function is pure. */
predicate isPure() { this instanceof PureVirtualFunction }
@@ -133,7 +125,7 @@ class VirtualFunction extends MemberFunction {
class PureVirtualFunction extends VirtualFunction {
PureVirtualFunction() { purefunctions(underlyingElement(this)) }
override string getAPrimaryQlClass() { result = "PureVirtualFunction" }
override string getCanonicalQLClass() { result = "PureVirtualFunction" }
}
/**
@@ -155,7 +147,7 @@ class PureVirtualFunction extends VirtualFunction {
class ConstMemberFunction extends MemberFunction {
ConstMemberFunction() { this.hasSpecifier("const") }
override string getAPrimaryQlClass() { result = "ConstMemberFunction" }
override string getCanonicalQLClass() { result = "ConstMemberFunction" }
}
/**
@@ -173,7 +165,7 @@ class ConstMemberFunction extends MemberFunction {
class Constructor extends MemberFunction {
Constructor() { functions(underlyingElement(this), _, 2) }
override string getAPrimaryQlClass() { result = "Constructor" }
override string getCanonicalQLClass() { result = "Constructor" }
/**
* Holds if this constructor serves as a default constructor.
@@ -232,7 +224,7 @@ class ConversionConstructor extends Constructor, ImplicitConversionFunction {
not this instanceof CopyConstructor
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not this instanceof MoveConstructor and result = "ConversionConstructor"
}
@@ -290,7 +282,7 @@ class CopyConstructor extends Constructor {
not exists(getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "CopyConstructor" }
override string getCanonicalQLClass() { result = "CopyConstructor" }
/**
* Holds if we cannot determine that this constructor will become a copy
@@ -347,7 +339,7 @@ class MoveConstructor extends Constructor {
not exists(getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "MoveConstructor" }
override string getCanonicalQLClass() { result = "MoveConstructor" }
/**
* Holds if we cannot determine that this constructor will become a move
@@ -398,7 +390,7 @@ class NoArgConstructor extends Constructor {
class Destructor extends MemberFunction {
Destructor() { functions(underlyingElement(this), _, 3) }
override string getAPrimaryQlClass() { result = "Destructor" }
override string getCanonicalQLClass() { result = "Destructor" }
/**
* Gets a compiler-generated action which destructs a base class or member
@@ -429,7 +421,7 @@ class Destructor extends MemberFunction {
class ConversionOperator extends MemberFunction, ImplicitConversionFunction {
ConversionOperator() { functions(underlyingElement(this), _, 4) }
override string getAPrimaryQlClass() { result = "ConversionOperator" }
override string getCanonicalQLClass() { result = "ConversionOperator" }
override Type getSourceType() { result = this.getDeclaringType() }
@@ -465,7 +457,7 @@ class CopyAssignmentOperator extends Operator {
not exists(getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "CopyAssignmentOperator" }
override string getCanonicalQLClass() { result = "CopyAssignmentOperator" }
}
/**
@@ -491,5 +483,5 @@ class MoveAssignmentOperator extends Operator {
not exists(getATemplateArgument())
}
override string getAPrimaryQlClass() { result = "MoveAssignmentOperator" }
override string getCanonicalQLClass() { result = "MoveAssignmentOperator" }
}

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for working with name qualifiers such as the `N::` in
* `N::f()`.
*/
import cpp
/**

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling namespaces, `using` directives and `using` declarations.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Type
import semmle.code.cpp.metrics.MetricNamespace
@@ -131,7 +127,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
*/
Location getBodyLocation() { namespace_decls(underlyingElement(this), _, _, result) }
override string getAPrimaryQlClass() { result = "NamespaceDeclarationEntry" }
override string getCanonicalQLClass() { result = "NamespaceDeclarationEntry" }
}
/**

View File

@@ -1,8 +1,3 @@
/**
* Provides a class for reasoning about nested field accesses, for example
* the access `myLine.start.x`.
*/
import cpp
/**
@@ -30,7 +25,7 @@ private Expr getUltimateQualifier(FieldAccess fa) {
}
/**
* A nested field access, for example the access `myLine.start.x`.
* Accesses to nested fields.
*/
class NestedFieldAccess extends FieldAccess {
Expr ultimateQualifier;
@@ -40,30 +35,6 @@ class NestedFieldAccess extends FieldAccess {
getTarget() = getANestedField(ultimateQualifier.getType().stripType())
}
/**
* Gets the outermost qualifier of this nested field access. In the
* following example, the access to `myLine.start.x` has outermost qualifier
* `myLine`:
* ```
* struct Point
* {
* float x, y;
* };
*
* struct Line
* {
* Point start, end;
* };
*
* void init()
* {
* Line myLine;
*
* myLine.start.x = 0.0f;
*
* // ...
* }
* ```
*/
/** Gets the ultimate qualifier of this nested field access. */
Expr getUltimateQualifier() { result = ultimateQualifier }
}

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Objective-C is no longer supported.
*/
import semmle.code.cpp.Class
private import semmle.code.cpp.internal.ResolveClass

View File

@@ -1,7 +1,3 @@
/**
* Provides a class that models parameters to functions.
*/
import semmle.code.cpp.Location
import semmle.code.cpp.Declaration
private import semmle.code.cpp.internal.ResolveClass
@@ -49,7 +45,7 @@ class Parameter extends LocalScopeVariable, @parameter {
result = "p#" + this.getIndex().toString()
}
override string getAPrimaryQlClass() { result = "Parameter" }
override string getCanonicalQLClass() { result = "Parameter" }
/**
* Gets the name of this parameter, including it's type.

View File

@@ -33,13 +33,11 @@ class PreprocessorDirective extends Locatable, @preprocdirect {
}
}
private class TPreprocessorBranchDirective = @ppd_branch or @ppd_else or @ppd_endif;
/**
* A C/C++ preprocessor branch related directive: `#if`, `#ifdef`,
* `#ifndef`, `#elif`, `#else` or `#endif`.
*/
class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBranchDirective {
abstract class PreprocessorBranchDirective extends PreprocessorDirective {
/**
* Gets the `#if`, `#ifdef` or `#ifndef` directive which matches this
* branching directive.
@@ -154,7 +152,7 @@ class PreprocessorIf extends PreprocessorBranch, @ppd_if {
class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
override string toString() { result = "#ifdef " + this.getHead() }
override string getAPrimaryQlClass() { result = "PreprocessorIfdef" }
override string getCanonicalQLClass() { result = "PreprocessorIfdef" }
}
/**

View File

@@ -1,11 +1,3 @@
/**
* Provides queries to pretty-print a C++ AST as a graph.
*
* By default, this will print the AST for all functions in the database. To change this behavior,
* extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
* you wish to view the AST for.
*/
import cpp
private import semmle.code.cpp.Print
@@ -15,9 +7,6 @@ private newtype TPrintASTConfiguration = MkPrintASTConfiguration()
* The query can extend this class to control which functions are printed.
*/
class PrintASTConfiguration extends TPrintASTConfiguration {
/**
* Gets a textual representation of this `PrintASTConfiguration`.
*/
string toString() { result = "PrintASTConfiguration" }
/**
@@ -107,9 +96,6 @@ private newtype TPrintASTNode =
* A node in the output tree.
*/
class PrintASTNode extends TPrintASTNode {
/**
* Gets a textual representation of this node in the PrintAST output tree.
*/
abstract string toString();
/**
@@ -169,7 +155,7 @@ class PrintASTNode extends TPrintASTNode {
* Retrieves the canonical QL class(es) for entity `el`
*/
private string qlClass(ElementBase el) {
result = "[" + concat(el.getAPrimaryQlClass(), ",") + "] "
result = "[" + concat(el.getCanonicalQLClass(), ",") + "] "
// Alternative implementation -- do not delete. It is useful for QL class discovery.
//result = "["+ concat(el.getAQlClass(), ",") + "] "
}
@@ -222,9 +208,6 @@ class ExprNode extends ASTNode {
result = expr.getValueCategoryString()
}
/**
* Gets the value of this expression, if it is a constant.
*/
string getValue() { result = expr.getValue() }
}
@@ -390,9 +373,6 @@ class ParametersNode extends PrintASTNode, TParametersNode {
override ASTNode getChild(int childIndex) { result.getAST() = func.getParameter(childIndex) }
/**
* Gets the `Function` for which this node represents the parameters.
*/
final Function getFunction() { result = func }
}
@@ -412,9 +392,6 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
result.getAST() = ctor.getInitializer(childIndex)
}
/**
* Gets the `Constructor` for which this node represents the initializer list.
*/
final Constructor getConstructor() { result = ctor }
}
@@ -434,9 +411,6 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
result.getAST() = dtor.getDestruction(childIndex)
}
/**
* Gets the `Destructor` for which this node represents the destruction list.
*/
final Destructor getDestructor() { result = dtor }
}
@@ -490,9 +464,6 @@ class FunctionNode extends ASTNode {
key = "semmle.order" and result = getOrder().toString()
}
/**
* Gets the `Function` this node represents.
*/
final Function getFunction() { result = func }
}
@@ -528,16 +499,11 @@ class ArrayAggregateLiteralNode extends ExprNode {
}
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
query predicate nodes(PrintASTNode node, string key, string value) {
node.shouldPrint() and
value = node.getProperty(key)
}
/**
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
* given `value`.
*/
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) {
exists(int childIndex |
source.shouldPrint() and
@@ -551,7 +517,6 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
)
}
/** Holds if property `key` of the graph has the given `value`. */
query predicate graphProperties(string key, string value) {
key = "semmle.graphKind" and value = "tree"
}

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling specifiers and attributes.
*/
import semmle.code.cpp.Element
private import semmle.code.cpp.internal.ResolveClass
@@ -16,7 +12,7 @@ class Specifier extends Element, @specifier {
result instanceof UnknownDefaultLocation
}
override string getAPrimaryQlClass() { result = "Specifier" }
override string getCanonicalQLClass() { result = "Specifier" }
/** Gets the name of this specifier. */
string getName() { specifiers(underlyingElement(this), result) }
@@ -37,7 +33,7 @@ class FunctionSpecifier extends Specifier {
this.hasName("explicit")
}
override string getAPrimaryQlClass() { result = "FunctionSpecifier)" }
override string getCanonicalQLClass() { result = "FunctionSpecifier)" }
}
/**
@@ -53,7 +49,7 @@ class StorageClassSpecifier extends Specifier {
this.hasName("mutable")
}
override string getAPrimaryQlClass() { result = "StorageClassSpecifier" }
override string getCanonicalQLClass() { result = "StorageClassSpecifier" }
}
/**
@@ -108,7 +104,7 @@ class AccessSpecifier extends Specifier {
)
}
override string getAPrimaryQlClass() { result = "AccessSpecifier" }
override string getCanonicalQLClass() { result = "AccessSpecifier" }
}
/**
@@ -238,7 +234,7 @@ class FormatAttribute extends GnuAttribute {
)
}
override string getAPrimaryQlClass() { result = "FormatAttribute" }
override string getCanonicalQLClass() { result = "FormatAttribute" }
}
/**

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling `struct`s.
*/
import semmle.code.cpp.Type
import semmle.code.cpp.Class
@@ -22,7 +18,7 @@ import semmle.code.cpp.Class
class Struct extends Class {
Struct() { usertypes(underlyingElement(this), _, 1) or usertypes(underlyingElement(this), _, 3) }
override string getAPrimaryQlClass() { result = "Struct" }
override string getCanonicalQLClass() { result = "Struct" }
override string explain() { result = "struct " + this.getName() }
@@ -43,7 +39,9 @@ class Struct extends Class {
class LocalStruct extends Struct {
LocalStruct() { isLocal() }
override string getAPrimaryQlClass() { not this instanceof LocalUnion and result = "LocalStruct" }
override string getCanonicalQLClass() {
not this instanceof LocalUnion and result = "LocalStruct"
}
}
/**
@@ -60,7 +58,7 @@ class LocalStruct extends Struct {
class NestedStruct extends Struct {
NestedStruct() { this.isMember() }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not this instanceof NestedUnion and result = "NestedStruct"
}

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for identifying files that contain test cases. It is often
* desirable to exclude these files from analysis.
*/
import semmle.code.cpp.File
/**

View File

@@ -1,8 +1,5 @@
/**
* Provides a hierarchy of classes for modeling C/C++ types.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.Member
import semmle.code.cpp.Function
private import semmle.code.cpp.internal.ResolveClass
@@ -325,7 +322,7 @@ class BuiltInType extends Type, @builtintype {
class ErroneousType extends BuiltInType {
ErroneousType() { builtintypes(underlyingElement(this), _, 1, _, _, _) }
override string getAPrimaryQlClass() { result = "ErroneousType" }
override string getCanonicalQLClass() { result = "ErroneousType" }
}
/**
@@ -345,7 +342,7 @@ class ErroneousType extends BuiltInType {
class UnknownType extends BuiltInType {
UnknownType() { builtintypes(underlyingElement(this), _, 2, _, _, _) }
override string getAPrimaryQlClass() { result = "UnknownType" }
override string getCanonicalQLClass() { result = "UnknownType" }
}
private predicate isArithmeticType(@builtintype type, int kind) {
@@ -364,7 +361,7 @@ private predicate isArithmeticType(@builtintype type, int kind) {
class ArithmeticType extends BuiltInType {
ArithmeticType() { isArithmeticType(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "ArithmeticType" }
override string getCanonicalQLClass() { result = "ArithmeticType" }
}
private predicate isIntegralType(@builtintype type, int kind) {
@@ -564,7 +561,7 @@ class IntegralType extends ArithmeticType, IntegralOrEnumType {
class BoolType extends IntegralType {
BoolType() { builtintypes(underlyingElement(this), _, 4, _, _, _) }
override string getAPrimaryQlClass() { result = "BoolType" }
override string getCanonicalQLClass() { result = "BoolType" }
}
/**
@@ -589,7 +586,7 @@ abstract class CharType extends IntegralType { }
class PlainCharType extends CharType {
PlainCharType() { builtintypes(underlyingElement(this), _, 5, _, _, _) }
override string getAPrimaryQlClass() { result = "PlainCharType" }
override string getCanonicalQLClass() { result = "PlainCharType" }
}
/**
@@ -602,7 +599,7 @@ class PlainCharType extends CharType {
class UnsignedCharType extends CharType {
UnsignedCharType() { builtintypes(underlyingElement(this), _, 6, _, _, _) }
override string getAPrimaryQlClass() { result = "UnsignedCharType" }
override string getCanonicalQLClass() { result = "UnsignedCharType" }
}
/**
@@ -615,7 +612,7 @@ class UnsignedCharType extends CharType {
class SignedCharType extends CharType {
SignedCharType() { builtintypes(underlyingElement(this), _, 7, _, _, _) }
override string getAPrimaryQlClass() { result = "SignedCharType" }
override string getCanonicalQLClass() { result = "SignedCharType" }
}
/**
@@ -632,7 +629,7 @@ class ShortType extends IntegralType {
builtintypes(underlyingElement(this), _, 10, _, _, _)
}
override string getAPrimaryQlClass() { result = "ShortType" }
override string getCanonicalQLClass() { result = "ShortType" }
}
/**
@@ -649,7 +646,7 @@ class IntType extends IntegralType {
builtintypes(underlyingElement(this), _, 13, _, _, _)
}
override string getAPrimaryQlClass() { result = "IntType" }
override string getCanonicalQLClass() { result = "IntType" }
}
/**
@@ -666,7 +663,7 @@ class LongType extends IntegralType {
builtintypes(underlyingElement(this), _, 16, _, _, _)
}
override string getAPrimaryQlClass() { result = "LongType" }
override string getCanonicalQLClass() { result = "LongType" }
}
/**
@@ -683,7 +680,7 @@ class LongLongType extends IntegralType {
builtintypes(underlyingElement(this), _, 19, _, _, _)
}
override string getAPrimaryQlClass() { result = "LongLongType" }
override string getCanonicalQLClass() { result = "LongLongType" }
}
/**
@@ -701,7 +698,7 @@ class Int128Type extends IntegralType {
builtintypes(underlyingElement(this), _, 37, _, _, _)
}
override string getAPrimaryQlClass() { result = "Int128Type" }
override string getCanonicalQLClass() { result = "Int128Type" }
}
private newtype TTypeDomain =
@@ -897,7 +894,7 @@ class DecimalFloatingPointType extends FloatingPointType {
class FloatType extends RealNumberType, BinaryFloatingPointType {
FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) }
override string getAPrimaryQlClass() { result = "FloatType" }
override string getCanonicalQLClass() { result = "FloatType" }
}
/**
@@ -909,7 +906,7 @@ class FloatType extends RealNumberType, BinaryFloatingPointType {
class DoubleType extends RealNumberType, BinaryFloatingPointType {
DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) }
override string getAPrimaryQlClass() { result = "DoubleType" }
override string getCanonicalQLClass() { result = "DoubleType" }
}
/**
@@ -921,7 +918,7 @@ class DoubleType extends RealNumberType, BinaryFloatingPointType {
class LongDoubleType extends RealNumberType, BinaryFloatingPointType {
LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) }
override string getAPrimaryQlClass() { result = "LongDoubleType" }
override string getCanonicalQLClass() { result = "LongDoubleType" }
}
/**
@@ -933,7 +930,7 @@ class LongDoubleType extends RealNumberType, BinaryFloatingPointType {
class Float128Type extends RealNumberType, BinaryFloatingPointType {
Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) }
override string getAPrimaryQlClass() { result = "Float128Type" }
override string getCanonicalQLClass() { result = "Float128Type" }
}
/**
@@ -945,7 +942,7 @@ class Float128Type extends RealNumberType, BinaryFloatingPointType {
class Decimal32Type extends RealNumberType, DecimalFloatingPointType {
Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) }
override string getAPrimaryQlClass() { result = "Decimal32Type" }
override string getCanonicalQLClass() { result = "Decimal32Type" }
}
/**
@@ -957,7 +954,7 @@ class Decimal32Type extends RealNumberType, DecimalFloatingPointType {
class Decimal64Type extends RealNumberType, DecimalFloatingPointType {
Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) }
override string getAPrimaryQlClass() { result = "Decimal64Type" }
override string getCanonicalQLClass() { result = "Decimal64Type" }
}
/**
@@ -969,7 +966,7 @@ class Decimal64Type extends RealNumberType, DecimalFloatingPointType {
class Decimal128Type extends RealNumberType, DecimalFloatingPointType {
Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) }
override string getAPrimaryQlClass() { result = "Decimal128Type" }
override string getCanonicalQLClass() { result = "Decimal128Type" }
}
/**
@@ -981,7 +978,7 @@ class Decimal128Type extends RealNumberType, DecimalFloatingPointType {
class VoidType extends BuiltInType {
VoidType() { builtintypes(underlyingElement(this), _, 3, _, _, _) }
override string getAPrimaryQlClass() { result = "VoidType" }
override string getCanonicalQLClass() { result = "VoidType" }
}
/**
@@ -997,7 +994,7 @@ class VoidType extends BuiltInType {
class WideCharType extends IntegralType {
WideCharType() { builtintypes(underlyingElement(this), _, 33, _, _, _) }
override string getAPrimaryQlClass() { result = "WideCharType" }
override string getCanonicalQLClass() { result = "WideCharType" }
}
/**
@@ -1009,7 +1006,7 @@ class WideCharType extends IntegralType {
class Char8Type extends IntegralType {
Char8Type() { builtintypes(underlyingElement(this), _, 51, _, _, _) }
override string getAPrimaryQlClass() { result = "Char8Type" }
override string getCanonicalQLClass() { result = "Char8Type" }
}
/**
@@ -1021,7 +1018,7 @@ class Char8Type extends IntegralType {
class Char16Type extends IntegralType {
Char16Type() { builtintypes(underlyingElement(this), _, 43, _, _, _) }
override string getAPrimaryQlClass() { result = "Char16Type" }
override string getCanonicalQLClass() { result = "Char16Type" }
}
/**
@@ -1033,7 +1030,7 @@ class Char16Type extends IntegralType {
class Char32Type extends IntegralType {
Char32Type() { builtintypes(underlyingElement(this), _, 44, _, _, _) }
override string getAPrimaryQlClass() { result = "Char32Type" }
override string getCanonicalQLClass() { result = "Char32Type" }
}
/**
@@ -1048,7 +1045,7 @@ class Char32Type extends IntegralType {
class NullPointerType extends BuiltInType {
NullPointerType() { builtintypes(underlyingElement(this), _, 34, _, _, _) }
override string getAPrimaryQlClass() { result = "NullPointerType" }
override string getCanonicalQLClass() { result = "NullPointerType" }
}
/**
@@ -1083,46 +1080,22 @@ class DerivedType extends Type, @derivedtype {
override Type stripType() { result = getBaseType().stripType() }
/**
* Holds if this type has the `__autoreleasing` specifier or if it points to
* a type with the `__autoreleasing` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isAutoReleasing() {
predicate isAutoReleasing() {
this.hasSpecifier("__autoreleasing") or
this.(PointerType).getBaseType().hasSpecifier("__autoreleasing")
}
/**
* Holds if this type has the `__strong` specifier or if it points to
* a type with the `__strong` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isStrong() {
predicate isStrong() {
this.hasSpecifier("__strong") or
this.(PointerType).getBaseType().hasSpecifier("__strong")
}
/**
* Holds if this type has the `__unsafe_unretained` specifier or if it points
* to a type with the `__unsafe_unretained` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isUnsafeRetained() {
predicate isUnsafeRetained() {
this.hasSpecifier("__unsafe_unretained") or
this.(PointerType).getBaseType().hasSpecifier("__unsafe_unretained")
}
/**
* Holds if this type has the `__weak` specifier or if it points to
* a type with the `__weak` specifier.
*
* DEPRECATED: use `hasSpecifier` directly instead.
*/
deprecated predicate isWeak() {
predicate isWeak() {
this.hasSpecifier("__weak") or
this.(PointerType).getBaseType().hasSpecifier("__weak")
}
@@ -1136,7 +1109,7 @@ class DerivedType extends Type, @derivedtype {
* ```
*/
class Decltype extends Type, @decltype {
override string getAPrimaryQlClass() { result = "Decltype" }
override string getCanonicalQLClass() { result = "Decltype" }
/**
* The expression whose type is being obtained by this decltype.
@@ -1209,7 +1182,7 @@ class Decltype extends Type, @decltype {
class PointerType extends DerivedType {
PointerType() { derivedtypes(underlyingElement(this), _, 1, _) }
override string getAPrimaryQlClass() { result = "PointerType" }
override string getCanonicalQLClass() { result = "PointerType" }
override int getPointerIndirectionLevel() {
result = 1 + this.getBaseType().getPointerIndirectionLevel()
@@ -1235,7 +1208,7 @@ class ReferenceType extends DerivedType {
derivedtypes(underlyingElement(this), _, 2, _) or derivedtypes(underlyingElement(this), _, 8, _)
}
override string getAPrimaryQlClass() { result = "ReferenceType" }
override string getCanonicalQLClass() { result = "ReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
@@ -1262,7 +1235,7 @@ class ReferenceType extends DerivedType {
class LValueReferenceType extends ReferenceType {
LValueReferenceType() { derivedtypes(underlyingElement(this), _, 2, _) }
override string getAPrimaryQlClass() { result = "LValueReferenceType" }
override string getCanonicalQLClass() { result = "LValueReferenceType" }
}
/**
@@ -1278,7 +1251,7 @@ class LValueReferenceType extends ReferenceType {
class RValueReferenceType extends ReferenceType {
RValueReferenceType() { derivedtypes(underlyingElement(this), _, 8, _) }
override string getAPrimaryQlClass() { result = "RValueReferenceType" }
override string getCanonicalQLClass() { result = "RValueReferenceType" }
override string explain() { result = "rvalue " + super.explain() }
}
@@ -1293,7 +1266,7 @@ class RValueReferenceType extends ReferenceType {
class SpecifiedType extends DerivedType {
SpecifiedType() { derivedtypes(underlyingElement(this), _, 3, _) }
override string getAPrimaryQlClass() { result = "SpecifiedType" }
override string getCanonicalQLClass() { result = "SpecifiedType" }
override int getSize() { result = this.getBaseType().getSize() }
@@ -1341,12 +1314,8 @@ class SpecifiedType extends DerivedType {
class ArrayType extends DerivedType {
ArrayType() { derivedtypes(underlyingElement(this), _, 4, _) }
override string getAPrimaryQlClass() { result = "ArrayType" }
override string getCanonicalQLClass() { result = "ArrayType" }
/**
* Holds if this array is declared to be of a constant size. See
* `getArraySize` and `getByteSize` to get the size of the array.
*/
predicate hasArraySize() { arraysizes(underlyingElement(this), _, _, _) }
/**
@@ -1412,7 +1381,7 @@ class GNUVectorType extends DerivedType {
*/
int getNumElements() { arraysizes(underlyingElement(this), result, _, _) }
override string getAPrimaryQlClass() { result = "GNUVectorType" }
override string getCanonicalQLClass() { result = "GNUVectorType" }
/**
* Gets the size, in bytes, of this vector type.
@@ -1443,7 +1412,7 @@ class GNUVectorType extends DerivedType {
class FunctionPointerType extends FunctionPointerIshType {
FunctionPointerType() { derivedtypes(underlyingElement(this), _, 6, _) }
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
override string getCanonicalQLClass() { result = "FunctionPointerType" }
override int getPointerIndirectionLevel() { result = 1 }
@@ -1461,7 +1430,7 @@ class FunctionPointerType extends FunctionPointerIshType {
class FunctionReferenceType extends FunctionPointerIshType {
FunctionReferenceType() { derivedtypes(underlyingElement(this), _, 7, _) }
override string getAPrimaryQlClass() { result = "FunctionReferenceType" }
override string getCanonicalQLClass() { result = "FunctionReferenceType" }
override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() }
@@ -1550,7 +1519,7 @@ class PointerToMemberType extends Type, @ptrtomember {
/** a printable representation of this named element */
override string toString() { result = this.getName() }
override string getAPrimaryQlClass() { result = "PointerToMemberType" }
override string getCanonicalQLClass() { result = "PointerToMemberType" }
/** the name of this type */
override string getName() { result = "..:: *" }
@@ -1595,25 +1564,16 @@ class RoutineType extends Type, @routinetype {
/** a printable representation of this named element */
override string toString() { result = this.getName() }
override string getAPrimaryQlClass() { result = "RoutineType" }
override string getCanonicalQLClass() { result = "RoutineType" }
override string getName() { result = "..()(..)" }
/**
* Gets the type of the `n`th parameter to this routine.
*/
Type getParameterType(int n) {
routinetypeargs(underlyingElement(this), n, unresolveElement(result))
}
/**
* Gets the type of a parameter to this routine.
*/
Type getAParameterType() { routinetypeargs(underlyingElement(this), _, unresolveElement(result)) }
/**
* Gets the return type of this routine.
*/
Type getReturnType() { routinetypes(underlyingElement(this), unresolveElement(result)) }
override string explain() {
@@ -1672,7 +1632,7 @@ class TemplateParameter extends UserType {
usertypes(underlyingElement(this), _, 7) or usertypes(underlyingElement(this), _, 8)
}
override string getAPrimaryQlClass() { result = "TemplateParameter" }
override string getCanonicalQLClass() { result = "TemplateParameter" }
override predicate involvesTemplateParameter() { any() }
}
@@ -1690,7 +1650,7 @@ class TemplateParameter extends UserType {
class TemplateTemplateParameter extends TemplateParameter {
TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) }
override string getAPrimaryQlClass() { result = "TemplateTemplateParameter" }
override string getCanonicalQLClass() { result = "TemplateTemplateParameter" }
}
/**
@@ -1702,7 +1662,7 @@ class TemplateTemplateParameter extends TemplateParameter {
class AutoType extends TemplateParameter {
AutoType() { usertypes(underlyingElement(this), "auto", 7) }
override string getAPrimaryQlClass() { result = "AutoType" }
override string getCanonicalQLClass() { result = "AutoType" }
override Location getLocation() {
suppressUnusedThis(this) and
@@ -1738,7 +1698,7 @@ private predicate suppressUnusedThis(Type t) { any() }
class TypeMention extends Locatable, @type_mention {
override string toString() { result = "type mention" }
override string getAPrimaryQlClass() { result = "TypeMention" }
override string getCanonicalQLClass() { result = "TypeMention" }
/**
* Gets the type being referenced by this type mention.

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling typedefs and type aliases.
*/
import semmle.code.cpp.Type
private import semmle.code.cpp.internal.ResolveClass
@@ -59,7 +55,7 @@ class TypedefType extends UserType {
class CTypedefType extends TypedefType {
CTypedefType() { usertypes(underlyingElement(this), _, 5) }
override string getAPrimaryQlClass() { result = "CTypedefType" }
override string getCanonicalQLClass() { result = "CTypedefType" }
override string explain() {
result = "typedef {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
@@ -75,7 +71,7 @@ class CTypedefType extends TypedefType {
class UsingAliasTypedefType extends TypedefType {
UsingAliasTypedefType() { usertypes(underlyingElement(this), _, 14) }
override string getAPrimaryQlClass() { result = "UsingAliasTypedefType" }
override string getCanonicalQLClass() { result = "UsingAliasTypedefType" }
override string explain() {
result = "using {" + this.getBaseType().explain() + "} as \"" + this.getName() + "\""
@@ -92,7 +88,7 @@ class UsingAliasTypedefType extends TypedefType {
class LocalTypedefType extends TypedefType {
LocalTypedefType() { isLocal() }
override string getAPrimaryQlClass() { result = "LocalTypedefType" }
override string getCanonicalQLClass() { result = "LocalTypedefType" }
}
/**
@@ -105,7 +101,7 @@ class LocalTypedefType extends TypedefType {
class NestedTypedefType extends TypedefType {
NestedTypedefType() { this.isMember() }
override string getAPrimaryQlClass() { result = "NestedTypedefType" }
override string getCanonicalQLClass() { result = "NestedTypedefType" }
/**
* DEPRECATED: use `.hasSpecifier("private")` instead.

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling `union`s.
*/
import semmle.code.cpp.Type
import semmle.code.cpp.Struct
@@ -17,7 +13,7 @@ import semmle.code.cpp.Struct
class Union extends Struct {
Union() { usertypes(underlyingElement(this), _, 3) }
override string getAPrimaryQlClass() { result = "Union" }
override string getCanonicalQLClass() { result = "Union" }
override string explain() { result = "union " + this.getName() }
@@ -39,7 +35,7 @@ class Union extends Struct {
class LocalUnion extends Union {
LocalUnion() { isLocal() }
override string getAPrimaryQlClass() { result = "LocalUnion" }
override string getCanonicalQLClass() { result = "LocalUnion" }
}
/**
@@ -57,7 +53,7 @@ class LocalUnion extends Union {
class NestedUnion extends Union {
NestedUnion() { this.isMember() }
override string getAPrimaryQlClass() { result = "NestedUnion" }
override string getCanonicalQLClass() { result = "NestedUnion" }
/** Holds if this member is private. */
predicate isPrivate() { this.hasSpecifier("private") }

View File

@@ -1,10 +1,6 @@
/**
* Provides classes for modeling user-defined types such as classes, typedefs
* and enums.
*/
import semmle.code.cpp.Declaration
import semmle.code.cpp.Type
import semmle.code.cpp.Member
import semmle.code.cpp.Function
private import semmle.code.cpp.internal.ResolveClass
@@ -24,7 +20,7 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
*/
override string getName() { usertypes(underlyingElement(this), result, _) }
override string getAPrimaryQlClass() { result = "UserType" }
override string getCanonicalQLClass() { result = "UserType" }
/**
* Gets the simple name of this type, without any template parameters. For example
@@ -88,9 +84,6 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
* type exactly - but this is not apparent from its subclasses
*/
/**
* Gets a child declaration within this user-defined type.
*/
Declaration getADeclaration() { none() }
override string explain() { result = this.getName() }
@@ -111,7 +104,7 @@ class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
override string getName() { result = getType().getName() }
override string getAPrimaryQlClass() { result = "TypeDeclarationEntry" }
override string getCanonicalQLClass() { result = "TypeDeclarationEntry" }
/**
* The type which is being declared or defined.

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling variables and their declarations.
*/
import semmle.code.cpp.Element
import semmle.code.cpp.exprs.Access
import semmle.code.cpp.Initializer
@@ -32,7 +28,7 @@ private import semmle.code.cpp.internal.ResolveClass
* can have multiple declarations.
*/
class Variable extends Declaration, @variable {
override string getAPrimaryQlClass() { result = "Variable" }
override string getCanonicalQLClass() { result = "Variable" }
/** Gets the initializer of this variable, if any. */
Initializer getInitializer() { result.getDeclaration() = this }
@@ -190,7 +186,7 @@ class Variable extends Declaration, @variable {
class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
override Variable getDeclaration() { result = getVariable() }
override string getAPrimaryQlClass() { result = "VariableDeclarationEntry" }
override string getCanonicalQLClass() { result = "VariableDeclarationEntry" }
/**
* Gets the variable which is being declared or defined.
@@ -249,7 +245,7 @@ class VariableDeclarationEntry extends DeclarationEntry, @var_decl {
class ParameterDeclarationEntry extends VariableDeclarationEntry {
ParameterDeclarationEntry() { param_decl_bind(underlyingElement(this), _, _) }
override string getAPrimaryQlClass() { result = "ParameterDeclarationEntry" }
override string getCanonicalQLClass() { result = "ParameterDeclarationEntry" }
/**
* Gets the function declaration or definition which this parameter
@@ -325,7 +321,7 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
*/
class LocalScopeVariable extends Variable, @localscopevariable {
/** Gets the function to which this variable belongs. */
Function getFunction() { none() } // overridden in subclasses
/*abstract*/ Function getFunction() { none() }
}
/**
@@ -363,7 +359,7 @@ class StackVariable extends LocalScopeVariable {
* A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`.
*/
class LocalVariable extends LocalScopeVariable, @localvariable {
override string getAPrimaryQlClass() { result = "LocalVariable" }
override string getCanonicalQLClass() { result = "LocalVariable" }
override string getName() { localvariables(underlyingElement(this), _, result) }
@@ -464,7 +460,7 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
exists(Namespace n | namespacembrs(unresolveElement(n), underlyingElement(this)))
}
override string getAPrimaryQlClass() { result = "NamespaceVariable" }
override string getCanonicalQLClass() { result = "NamespaceVariable" }
}
/**
@@ -485,7 +481,7 @@ class NamespaceVariable extends GlobalOrNamespaceVariable {
class GlobalVariable extends GlobalOrNamespaceVariable {
GlobalVariable() { not this instanceof NamespaceVariable }
override string getAPrimaryQlClass() { result = "GlobalVariable" }
override string getCanonicalQLClass() { result = "GlobalVariable" }
}
/**
@@ -505,7 +501,7 @@ class GlobalVariable extends GlobalOrNamespaceVariable {
class MemberVariable extends Variable, @membervariable {
MemberVariable() { this.isMember() }
override string getAPrimaryQlClass() { result = "MemberVariable" }
override string getCanonicalQLClass() { result = "MemberVariable" }
/** Holds if this member is private. */
predicate isPrivate() { this.hasSpecifier("private") }
@@ -582,7 +578,7 @@ class TemplateVariable extends Variable {
* float a;
* }
*
* template<typename T>
* template<type T>
* void myTemplateFunction() {
* T b;
* }

View File

@@ -6,7 +6,7 @@ import semmle.code.cpp.Type
class CharPointerType extends PointerType {
CharPointerType() { this.getBaseType() instanceof CharType }
override string getAPrimaryQlClass() { result = "CharPointerType" }
override string getCanonicalQLClass() { result = "CharPointerType" }
}
/**
@@ -15,7 +15,7 @@ class CharPointerType extends PointerType {
class IntPointerType extends PointerType {
IntPointerType() { this.getBaseType() instanceof IntType }
override string getAPrimaryQlClass() { result = "IntPointerType" }
override string getCanonicalQLClass() { result = "IntPointerType" }
}
/**
@@ -24,7 +24,7 @@ class IntPointerType extends PointerType {
class VoidPointerType extends PointerType {
VoidPointerType() { this.getBaseType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "VoidPointerType" }
override string getCanonicalQLClass() { result = "VoidPointerType" }
}
/**
@@ -36,7 +36,7 @@ class Size_t extends Type {
this.hasName("size_t")
}
override string getAPrimaryQlClass() { result = "Size_t" }
override string getCanonicalQLClass() { result = "Size_t" }
}
/**
@@ -48,7 +48,7 @@ class Ssize_t extends Type {
this.hasName("ssize_t")
}
override string getAPrimaryQlClass() { result = "Ssize_t" }
override string getCanonicalQLClass() { result = "Ssize_t" }
}
/**
@@ -60,7 +60,7 @@ class Ptrdiff_t extends Type {
this.hasName("ptrdiff_t")
}
override string getAPrimaryQlClass() { result = "Ptrdiff_t" }
override string getCanonicalQLClass() { result = "Ptrdiff_t" }
}
/**
@@ -72,7 +72,7 @@ class Intmax_t extends Type {
this.hasName("intmax_t")
}
override string getAPrimaryQlClass() { result = "Intmax_t" }
override string getCanonicalQLClass() { result = "Intmax_t" }
}
/**
@@ -84,7 +84,7 @@ class Uintmax_t extends Type {
this.hasName("uintmax_t")
}
override string getAPrimaryQlClass() { result = "Uintmax_t" }
override string getCanonicalQLClass() { result = "Uintmax_t" }
}
/**
@@ -100,7 +100,7 @@ class Wchar_t extends Type {
this.hasName("wchar_t")
}
override string getAPrimaryQlClass() { result = "Wchar_t" }
override string getCanonicalQLClass() { result = "Wchar_t" }
}
/**
@@ -176,5 +176,5 @@ class MicrosoftInt64Type extends IntegralType {
class BuiltInVarArgsList extends Type {
BuiltInVarArgsList() { this.hasName("__builtin_va_list") }
override string getAPrimaryQlClass() { result = "BuiltInVarArgsList" }
override string getCanonicalQLClass() { result = "BuiltInVarArgsList" }
}

View File

@@ -1,7 +1,3 @@
/**
* Provides predicates for identifying function calls that open or close a file.
*/
import cpp
/**

View File

@@ -20,7 +20,7 @@ class PrintfFormatAttribute extends FormatAttribute {
* function by its use of the GNU `format` attribute.
*/
class AttributeFormattingFunction extends FormattingFunction {
override string getAPrimaryQlClass() { result = "AttributeFormattingFunction" }
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
AttributeFormattingFunction() {
exists(PrintfFormatAttribute printf_attrib |
@@ -49,18 +49,6 @@ predicate primitiveVariadicFormatter(TopLevelFunction f, int formatParamIndex) {
)
}
/**
* A standard function such as `vsprintf` that has an output parameter
* and a variable argument list of type `va_arg`.
*/
private predicate primitiveVariadicFormatterOutput(TopLevelFunction f, int outputParamIndex) {
// note: this might look like the regular expression in `primitiveVariadicFormatter`, but
// there is one important difference: the [fs] part is not optional, as these classify
// the `printf` variants that write to a buffer.
// Conveniently, these buffer parameters are all at index 0.
f.getName().regexpMatch("_?_?va?[fs]n?w?printf(_s)?(_p)?(_l)?") and outputParamIndex = 0
}
private predicate callsVariadicFormatter(Function f, int formatParamIndex) {
exists(FunctionCall fc, int i |
variadicFormatter(fc.getTarget(), i) and
@@ -69,26 +57,6 @@ private predicate callsVariadicFormatter(Function f, int formatParamIndex) {
)
}
private predicate callsVariadicFormatterOutput(Function f, int outputParamIndex) {
exists(FunctionCall fc, int i |
fc.getEnclosingFunction() = f and
variadicFormatterOutput(fc.getTarget(), i) and
fc.getArgument(i) = f.getParameter(outputParamIndex).getAnAccess()
)
}
/**
* Holds if `f` is a function such as `vprintf` that takes variable argument list
* of type `va_arg` and writes formatted output to a buffer given as a parameter at
* index `outputParamIndex`, if any.
*/
private predicate variadicFormatterOutput(Function f, int outputParamIndex) {
primitiveVariadicFormatterOutput(f, outputParamIndex)
or
not f.isVarargs() and
callsVariadicFormatterOutput(f, outputParamIndex)
}
/**
* Holds if `f` is a function such as `vprintf` that has a format parameter
* (at `formatParamIndex`) and a variable argument list of type `va_arg`.
@@ -105,13 +73,11 @@ predicate variadicFormatter(Function f, int formatParamIndex) {
* string and a variable number of arguments.
*/
class UserDefinedFormattingFunction extends FormattingFunction {
override string getAPrimaryQlClass() { result = "UserDefinedFormattingFunction" }
override string getCanonicalQLClass() { result = "UserDefinedFormattingFunction" }
UserDefinedFormattingFunction() { isVarargs() and callsVariadicFormatter(this, _) }
override int getFormatParameterIndex() { callsVariadicFormatter(this, result) }
override int getOutputParameterIndex() { callsVariadicFormatterOutput(this, result) }
}
/**
@@ -120,7 +86,7 @@ class UserDefinedFormattingFunction extends FormattingFunction {
class FormattingFunctionCall extends Expr {
FormattingFunctionCall() { this.(Call).getTarget() instanceof FormattingFunction }
override string getAPrimaryQlClass() { result = "FormattingFunctionCall" }
override string getCanonicalQLClass() { result = "FormattingFunctionCall" }
/**
* Gets the formatting function being called.

View File

@@ -1,7 +1,3 @@
/**
* Provides a class for calculating the possible length of string expressions.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.controlflow.SSA

View File

@@ -23,7 +23,8 @@ abstract class MutexType extends Type {
abstract predicate trylockAccess(FunctionCall fc, Expr arg);
/**
* Holds if `fc` is a call that unlocks mutex `arg` of this type.
* Holds if `fc` is a call that unlocks mutex `arg`
* of this type.
*/
abstract predicate unlockAccess(FunctionCall fc, Expr arg);
@@ -37,7 +38,8 @@ abstract class MutexType extends Type {
}
/**
* Gets a call that locks or tries to lock any mutex of this type.
* Holds if `fc` is a call that locks or tries to lock any
* mutex of this type.
*/
FunctionCall getLockAccess() {
result = getMustlockAccess() or
@@ -45,44 +47,44 @@ abstract class MutexType extends Type {
}
/**
* Gets a call that always locks any mutex of this type.
* Holds if `fc` is a call that always locks any mutex of this type.
*/
FunctionCall getMustlockAccess() { this.mustlockAccess(result, _) }
/**
* Gets a call that tries to lock any mutex of this type,
* Holds if `fc` is a call that tries to lock any mutex of this type,
* by may return without success.
*/
FunctionCall getTrylockAccess() { this.trylockAccess(result, _) }
/**
* Gets a call that unlocks any mutex of this type.
* Holds if `fc` is a call that unlocks any mutex of this type.
*/
FunctionCall getUnlockAccess() { this.unlockAccess(result, _) }
/**
* DEPRECATED: use mustlockAccess(fc, arg) instead.
* DEPRECATED: use mustlockAccess(fc, arg) instead
*/
deprecated Function getMustlockFunction() { result = getMustlockAccess().getTarget() }
/**
* DEPRECATED: use trylockAccess(fc, arg) instead.
* DEPRECATED: use trylockAccess(fc, arg) instead
*/
deprecated Function getTrylockFunction() { result = getTrylockAccess().getTarget() }
/**
* DEPRECATED: use lockAccess(fc, arg) instead.
* DEPRECATED: use lockAccess(fc, arg) instead
*/
deprecated Function getLockFunction() { result = getLockAccess().getTarget() }
/**
* DEPRECATED: use unlockAccess(fc, arg) instead.
* DEPRECATED: use unlockAccess(fc, arg) instead
*/
deprecated Function getUnlockFunction() { result = getUnlockAccess().getTarget() }
}
/**
* Gets a function that looks like a lock function.
* A function that looks like a lock function.
*/
private Function mustlockCandidate() {
exists(string name | name = result.getName() |
@@ -92,7 +94,7 @@ private Function mustlockCandidate() {
}
/**
* Gets a function that looks like a try-lock function.
* A function that looks like a try-lock function.
*/
private Function trylockCandidate() {
exists(string name | name = result.getName() |
@@ -102,7 +104,7 @@ private Function trylockCandidate() {
}
/**
* Gets a function that looks like an unlock function.
* A function that looks like an unlock function.
*/
private Function unlockCandidate() {
exists(string name | name = result.getName() |
@@ -169,10 +171,7 @@ class DefaultMutexType extends MutexType {
}
}
/**
* Holds if `arg` is the mutex argument of a call to lock or unlock and
* `argType` is the type of the mutex.
*/
/** Get the mutex argument of a call to lock or unlock. */
private predicate lockArg(Expr arg, MutexType argType, FunctionCall call) {
argType = arg.getUnderlyingType().stripType() and
(
@@ -185,31 +184,18 @@ private predicate lockArg(Expr arg, MutexType argType, FunctionCall call) {
// `MutexType.mustlockAccess`.
}
/**
* Holds if `call` is a call that locks or tries to lock its argument `arg`.
*/
predicate lockCall(Expr arg, FunctionCall call) {
exists(MutexType t | lockArg(arg, t, call) and call = t.getLockAccess())
}
/**
* Holds if `call` is a call that always locks its argument `arg`.
*/
predicate mustlockCall(Expr arg, FunctionCall call) {
exists(MutexType t | lockArg(arg, t, call) and call = t.getMustlockAccess())
}
/**
* Holds if `call` is a call that tries to lock its argument `arg`, but may
* return without success.
*/
predicate trylockCall(Expr arg, FunctionCall call) {
exists(MutexType t | lockArg(arg, t, call) and call = t.getTrylockAccess())
}
/**
* Holds if `call` is a call that unlocks its argument `arg`.
*/
predicate unlockCall(Expr arg, FunctionCall call) {
exists(MutexType t | lockArg(arg, t, call) and call = t.getUnlockAccess())
}

View File

@@ -53,13 +53,26 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
}
/**
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
* Holds if the call context `ctx` reduces the set of viable dispatch
* targets of `ma` in `c`.
*/
predicate mayBenefitFromCallContext(Call call, Function f) { none() }
predicate reducedViableImplInCallContext(Call call, Function f, Call ctx) { none() }
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s for which the context makes a difference.
*/
Function viableImplInCallContext(Call call, Call ctx) { none() }
Function prunedViableImplInCallContext(Call call, Call ctx) { none() }
/**
* Holds if flow returning from `m` to `ma` might return further and if
* this path restricts the set of call sites that can be returned to.
*/
predicate reducedViableImplInReturn(Function f, Call call) { none() }
/**
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s and results for which the return flow from the
* result to `ma` restricts the possible context `ctx`.
*/
Function prunedViableImplInCallContextReverse(Call call, Call ctx) { none() }

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -22,7 +22,7 @@ private module Cached {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(p))
)
}
@@ -147,6 +147,54 @@ private module Cached {
}
}
private module LocalFlowBigStep {
private predicate localFlowEntry(Node n) {
Cand::cand(_, n) and
(
n instanceof ParameterNode or
n instanceof OutNode or
readStep(_, _, n) or
n instanceof CastNode
)
}
private predicate localFlowExit(Node n) {
Cand::cand(_, n) and
(
n instanceof ArgumentNode
or
n instanceof ReturnNode
or
readStep(n, _, _)
or
n instanceof CastNode
or
n =
any(PostUpdateNode pun | Cand::parameterValueFlowsToPreUpdateCand(_, pun))
.getPreUpdateNode()
)
}
pragma[nomagic]
private predicate localFlowStepPlus(Node node1, Node node2) {
localFlowEntry(node1) and
simpleLocalFlowStep(node1, node2) and
node1 != node2
or
exists(Node mid |
localFlowStepPlus(node1, mid) and
simpleLocalFlowStep(mid, node2) and
not mid instanceof CastNode
)
}
pragma[nomagic]
predicate localFlowBigStep(Node node1, Node node2) {
localFlowStepPlus(node1, node2) and
localFlowExit(node2)
}
}
/**
* The final flow-through calculation:
*
@@ -170,10 +218,10 @@ private module Cached {
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node))
else any()
}
@@ -186,7 +234,7 @@ private module Cached {
// local flow
exists(Node mid |
parameterValueFlow(p, mid, read) and
simpleLocalFlowStep(mid, node)
LocalFlowBigStep::localFlowBigStep(mid, node)
)
or
// read
@@ -195,26 +243,19 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
}
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
parameterValueFlowArg(p, arg, TReadStepTypesNone()) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
argumentValueFlowsThrough(arg, TReadStepTypesNone(), node)
)
}
@@ -251,11 +292,11 @@ private module Cached {
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out))
)
}
@@ -289,67 +330,6 @@ private module Cached {
import Final
}
import FlowThrough
cached
private module DispatchWithCallContext {
/**
* Holds if the call context `ctx` reduces the set of viable run-time
* dispatch targets of call `call` in `c`.
*/
cached
predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) {
exists(int tgts, int ctxtgts |
mayBenefitFromCallContext(call, c) and
c = viableCallable(ctx) and
ctxtgts = count(viableImplInCallContext(call, ctx)) and
tgts = strictcount(viableCallable(call)) and
ctxtgts < tgts
)
}
/**
* Gets a viable run-time dispatch target for the call `call` in the
* context `ctx`. This is restricted to those calls for which a context
* makes a difference.
*/
cached
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
reducedViableImplInCallContext(call, _, ctx)
}
/**
* Holds if flow returning from callable `c` to call `call` might return
* further and if this path restricts the set of call sites that can be
* returned to.
*/
cached
predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) {
exists(int tgts, int ctxtgts |
mayBenefitFromCallContext(call, _) and
c = viableCallable(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContext(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallable(ctx) = call.getEnclosingCallable()) and
ctxtgts < tgts
)
}
/**
* Gets a viable run-time dispatch target for the call `call` in the
* context `ctx`. This is restricted to those calls and results for which
* the return flow from the result to `call` restricts the possible context
* `ctx`.
*/
cached
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
reducedViableImplInReturn(result, call)
}
}
import DispatchWithCallContext
/**
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
@@ -364,8 +344,8 @@ private module Cached {
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
contentType = getErasedNodeTypeBound(node1) and
containerType = getErasedNodeTypeBound(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -374,8 +354,8 @@ private module Cached {
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
contentType = getErasedNodeTypeBound(n1) and
containerType = getErasedNodeTypeBound(n2)
)
}
@@ -391,6 +371,8 @@ private module Cached {
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
}
import FlowThrough
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -466,8 +448,8 @@ private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
container = getErasedNodeTypeBound(n1) and
content = getErasedNodeTypeBound(n2)
}
private newtype TReadStepTypesOption =
@@ -730,6 +712,9 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallable(call) and cc instanceof CallContextReturn
}
pragma[noinline]
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
predicate read = readStep/3;
/** An optional Boolean value. */
@@ -769,13 +754,6 @@ abstract class AccessPathFront extends TAccessPathFront {
abstract boolean toBoolNonEmpty();
predicate headUsesContent(TypedContent tc) { this = TFrontHead(tc) }
predicate isClearedAt(Node n) {
exists(TypedContent tc |
this.headUsesContent(tc) and
clearsContent(n, tc.getContent())
)
}
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -37,12 +37,21 @@ module Consistency {
)
}
query predicate uniqueType(Node n, string msg) {
query predicate uniqueTypeBound(Node n, string msg) {
exists(int c |
n instanceof RelevantNode and
c = count(getNodeType(n)) and
c = count(n.getTypeBound()) and
c != 1 and
msg = "Node should have one type but has " + c + "."
msg = "Node should have one type bound but has " + c + "."
)
}
query predicate uniqueTypeRepr(Node n, string msg) {
exists(int c |
n instanceof RelevantNode and
c = count(getErasedRepr(n.getTypeBound())) and
c != 1 and
msg = "Node should have one type representation but has " + c + "."
)
}
@@ -95,7 +104,7 @@ module Consistency {
msg = "Local flow step does not preserve enclosing callable."
}
private DataFlowType typeRepr() { result = getNodeType(_) }
private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) }
query predicate compatibleTypesReflexive(DataFlowType t, string msg) {
t = typeRepr() and

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -217,19 +217,16 @@ predicate readStep(Node node1, Content f, Node node2) {
}
/**
* Holds if values stored inside content `c` are cleared at node `n`.
* Gets a representative (boxed) type for `t` for the purpose of pruning
* possible flow. A single type is used for all numeric types to account for
* numeric conversions, and otherwise the erasure is used.
*/
predicate clearsContent(Node n, Content c) {
none() // stub implementation
}
/** Gets the type of `n` used for type pruning. */
Type getNodeType(Node n) {
suppressUnusedNode(n) and
Type getErasedRepr(Type t) {
suppressUnusedType(t) and
result instanceof VoidType // stub implementation
}
/** Gets a string representation of a type returned by `getNodeType`. */
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(Type t) { none() } // stub implementation
/**
@@ -241,7 +238,7 @@ predicate compatibleTypes(Type t1, Type t2) {
any() // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
private predicate suppressUnusedType(Type t) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers

View File

@@ -50,25 +50,13 @@ class Node extends TNode {
/** Gets the type of this node. */
Type getType() { none() } // overridden in subclasses
/**
* Gets the expression corresponding to this node, if any. This predicate
* only has a result on nodes that represent the value of evaluating the
* expression. For data flowing _out of_ an expression, like when an
* argument is passed by reference, use `asDefiningArgument` instead of
* `asExpr`.
*/
/** Gets the expression corresponding to this node, if any. */
Expr asExpr() { result = this.(ExprNode).getExpr() }
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() }
/**
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
* This predicate should be used instead of `asExpr` when referring to the
* value of a reference argument _after_ the call has returned. For example,
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
* that represents the new value of `x`.
*/
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
/**
@@ -395,9 +383,7 @@ class PreConstructorInitThis extends Node, TPreConstructorInitThis {
}
/**
* Gets the `Node` corresponding to the value of evaluating `e`. For data
* flowing _out of_ an expression, like when an argument is passed by
* reference, use `definitionByReferenceNodeFromArgument` instead.
* Gets the `Node` corresponding to `e`.
*/
ExprNode exprNode(Expr e) { result.getExpr() = e }

View File

@@ -120,25 +120,15 @@ private module PartialDefinitions {
)
}
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
/**
* Gets the subBasicBlock where this `PartialDefinition` is defined.
*/
ControlFlowNode getSubBasicBlockStart() { result = node }
/**
* Holds if this `PartialDefinition` defines variable `v` at control-flow
* node `cfn`.
*/
pragma[noinline]
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
innerDefinedExpr = v.getAnAccess() and
cfn = node
}
/**
* Holds if this partial definition may modify `inner` (or what it points
* to) through `outer`. These expressions will never be `Conversion`s.
@@ -198,7 +188,7 @@ module FlowVar_internal {
predicate fullySupportedSsaVariable(Variable v) {
v = any(SsaDefinition def).getAVariable() and
// A partially-defined variable is handled using the partial definitions logic.
not any(PartialDefinition p).partiallyDefinesVariableAt(v, _) and
not any(PartialDefinition p).partiallyDefines(v) and
// SSA variables do not exist before their first assignment, but one
// feature of this data flow library is to track where uninitialized data
// ends up.
@@ -242,7 +232,7 @@ module FlowVar_internal {
or
assignmentLikeOperation(sbb, v, _, _)
or
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, sbb))
sbb = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
or
blockVarDefinedByVariable(sbb, v)
)
@@ -373,7 +363,8 @@ module FlowVar_internal {
override predicate definedPartiallyAt(Expr e) {
exists(PartialDefinition p |
p.partiallyDefinesVariableAt(v, sbb) and
p.partiallyDefines(v) and
sbb = p.getSubBasicBlockStart() and
p.definesExpressions(_, e)
)
}
@@ -436,7 +427,7 @@ module FlowVar_internal {
/**
* Gets a variable that is assigned in this loop and read outside the loop.
*/
Variable getARelevantVariable() {
private Variable getARelevantVariable() {
result = this.getAVariableAssignedInLoop() and
exists(VariableAccess va |
va.getTarget() = result and
@@ -481,16 +472,10 @@ module FlowVar_internal {
reachesWithoutAssignment(bb.getAPredecessor(), v) and
this.bbInLoop(bb)
) and
not assignsToVar(bb, v)
not assignmentLikeOperation(bb.getANode(), v, _, _)
}
}
pragma[noinline]
private predicate assignsToVar(BasicBlock bb, Variable v) {
assignmentLikeOperation(bb.getANode(), v, _, _) and
exists(AlwaysTrueUponEntryLoop loop | v = loop.getARelevantVariable())
}
/**
* Holds if `loop` always assigns to `v` before leaving through an edge
* from `bbInside` in its condition to `bbOutside` outside the loop. Also,
@@ -751,7 +736,7 @@ module FlowVar_internal {
exists(Variable v | not fullySupportedSsaVariable(v) |
assignmentLikeOperation(this, v, _, _)
or
exists(PartialDefinition p | p.partiallyDefinesVariableAt(v, this))
this = any(PartialDefinition p | p.partiallyDefines(v)).getSubBasicBlockStart()
// It is not necessary to cut the basic blocks at `Initializer` nodes
// because the affected variable can have no _other_ value before its
// initializer. It is not necessary to cut basic blocks at procedure

View File

@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
* To create a configuration, extend this class with a subclass whose
* characteristic predicate is a unique singleton string. For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*

View File

@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
* To create a configuration, extend this class with a subclass whose
* characteristic predicate is a unique singleton string. For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling accesses including variable accesses, enum
* constant accesses and function accesses.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.Variable
import semmle.code.cpp.Enum
@@ -41,7 +36,7 @@ class Access extends Expr, NameQualifiableElement, @access {
* ```
*/
class EnumConstantAccess extends Access, @varaccess {
override string getAPrimaryQlClass() { result = "EnumConstantAccess" }
override string getCanonicalQLClass() { result = "EnumConstantAccess" }
EnumConstantAccess() {
exists(EnumConstant c | varbind(underlyingElement(this), unresolveElement(c)))
@@ -66,7 +61,7 @@ class EnumConstantAccess extends Access, @varaccess {
* ```
*/
class VariableAccess extends Access, @varaccess {
override string getAPrimaryQlClass() { result = "VariableAccess" }
override string getCanonicalQLClass() { result = "VariableAccess" }
VariableAccess() {
not exists(EnumConstant c | varbind(underlyingElement(this), unresolveElement(c)))
@@ -171,7 +166,7 @@ class VariableAccess extends Access, @varaccess {
* ```
*/
class FieldAccess extends VariableAccess {
override string getAPrimaryQlClass() { result = "FieldAccess" }
override string getCanonicalQLClass() { result = "FieldAccess" }
FieldAccess() { exists(Field f | varbind(underlyingElement(this), unresolveElement(f))) }
@@ -199,7 +194,7 @@ class FieldAccess extends VariableAccess {
* ```
*/
class PointerFieldAccess extends FieldAccess {
override string getAPrimaryQlClass() { result = "PointerFieldAccess" }
override string getCanonicalQLClass() { result = "PointerFieldAccess" }
PointerFieldAccess() {
exists(PointerType t |
@@ -216,7 +211,7 @@ class PointerFieldAccess extends FieldAccess {
* distinguish whether or not the type of `obj` is a reference type.
*/
class DotFieldAccess extends FieldAccess {
override string getAPrimaryQlClass() { result = "DotFieldAccess" }
override string getCanonicalQLClass() { result = "DotFieldAccess" }
DotFieldAccess() { exists(Class c | c = getQualifier().getFullyConverted().getUnspecifiedType()) }
}
@@ -237,7 +232,7 @@ class DotFieldAccess extends FieldAccess {
* ```
*/
class ReferenceFieldAccess extends DotFieldAccess {
override string getAPrimaryQlClass() { result = "ReferenceFieldAccess" }
override string getCanonicalQLClass() { result = "ReferenceFieldAccess" }
ReferenceFieldAccess() { exprHasReferenceConversion(this.getQualifier()) }
}
@@ -258,7 +253,7 @@ class ReferenceFieldAccess extends DotFieldAccess {
* ```
*/
class ValueFieldAccess extends DotFieldAccess {
override string getAPrimaryQlClass() { result = "ValueFieldAccess" }
override string getCanonicalQLClass() { result = "ValueFieldAccess" }
ValueFieldAccess() { not exprHasReferenceConversion(this.getQualifier()) }
}
@@ -312,7 +307,7 @@ private predicate exprHasReferenceConversion(Expr e) { referenceConversion(e.get
* `ImplicitThisFieldAccess`.
*/
class ImplicitThisFieldAccess extends FieldAccess {
override string getAPrimaryQlClass() { result = "ImplicitThisFieldAccess" }
override string getCanonicalQLClass() { result = "ImplicitThisFieldAccess" }
ImplicitThisFieldAccess() { not exists(this.getQualifier()) }
}
@@ -337,7 +332,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
override predicate isConstant() { any() }
override string getAPrimaryQlClass() { result = "PointerToFieldLiteral" }
override string getCanonicalQLClass() { result = "PointerToFieldLiteral" }
}
/**
@@ -354,7 +349,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
class FunctionAccess extends Access, @routineexpr {
FunctionAccess() { not iscall(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "FunctionAccess" }
override string getCanonicalQLClass() { result = "FunctionAccess" }
/** Gets the accessed function. */
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }
@@ -404,7 +399,7 @@ class ParamAccessForType extends Expr, @param_ref {
* ```
*/
class TypeName extends Expr, @type_operand {
override string getAPrimaryQlClass() { result = "TypeName" }
override string getCanonicalQLClass() { result = "TypeName" }
override string toString() { result = this.getType().getName() }
}
@@ -423,7 +418,7 @@ class TypeName extends Expr, @type_operand {
* `OverloadedArrayExpr`.
*/
class ArrayExpr extends Expr, @subscriptexpr {
override string getAPrimaryQlClass() { result = "ArrayExpr" }
override string getCanonicalQLClass() { result = "ArrayExpr" }
/**
* Gets the array or pointer expression being subscripted.

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling arithmetic operations such as `+`, `-`, `*`
* and `++`.
*/
import semmle.code.cpp.exprs.Expr
/**
@@ -19,7 +14,7 @@ class UnaryArithmeticOperation extends UnaryOperation, @un_arith_op_expr { }
class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "UnaryMinusExpr" }
override string getCanonicalQLClass() { result = "UnaryMinusExpr" }
override int getPrecedence() { result = 16 }
}
@@ -33,7 +28,7 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "UnaryPlusExpr" }
override string getCanonicalQLClass() { result = "UnaryPlusExpr" }
override int getPrecedence() { result = 16 }
}
@@ -50,7 +45,7 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
class ConjugationExpr extends UnaryArithmeticOperation, @conjugation {
override string getOperator() { result = "~" }
override string getAPrimaryQlClass() { result = "ConjugationExpr" }
override string getCanonicalQLClass() { result = "ConjugationExpr" }
}
/**
@@ -112,7 +107,7 @@ class PostfixCrementOperation extends CrementOperation, @postfix_crement_expr {
class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preincrexpr {
override string getOperator() { result = "++" }
override string getAPrimaryQlClass() { result = "PrefixIncrExpr" }
override string getCanonicalQLClass() { result = "PrefixIncrExpr" }
override int getPrecedence() { result = 16 }
}
@@ -128,7 +123,7 @@ class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preinc
class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predecrexpr {
override string getOperator() { result = "--" }
override string getAPrimaryQlClass() { result = "PrefixDecrExpr" }
override string getCanonicalQLClass() { result = "PrefixDecrExpr" }
override int getPrecedence() { result = 16 }
}
@@ -144,7 +139,7 @@ class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predec
class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @postincrexpr {
override string getOperator() { result = "++" }
override string getAPrimaryQlClass() { result = "PostfixIncrExpr" }
override string getCanonicalQLClass() { result = "PostfixIncrExpr" }
override int getPrecedence() { result = 17 }
@@ -162,7 +157,7 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @postdecrexpr {
override string getOperator() { result = "--" }
override string getAPrimaryQlClass() { result = "PostfixDecrExpr" }
override string getCanonicalQLClass() { result = "PostfixDecrExpr" }
override int getPrecedence() { result = 17 }
@@ -180,7 +175,7 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
override string getOperator() { result = "__real" }
override string getAPrimaryQlClass() { result = "RealPartExpr" }
override string getCanonicalQLClass() { result = "RealPartExpr" }
}
/**
@@ -194,7 +189,7 @@ class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
class ImaginaryPartExpr extends UnaryArithmeticOperation, @imagpartexpr {
override string getOperator() { result = "__imag" }
override string getAPrimaryQlClass() { result = "ImaginaryPartExpr" }
override string getCanonicalQLClass() { result = "ImaginaryPartExpr" }
}
/**
@@ -213,7 +208,7 @@ class BinaryArithmeticOperation extends BinaryOperation, @bin_arith_op_expr { }
class AddExpr extends BinaryArithmeticOperation, @addexpr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "AddExpr" }
override string getCanonicalQLClass() { result = "AddExpr" }
override int getPrecedence() { result = 13 }
}
@@ -227,7 +222,7 @@ class AddExpr extends BinaryArithmeticOperation, @addexpr {
class SubExpr extends BinaryArithmeticOperation, @subexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "SubExpr" }
override string getCanonicalQLClass() { result = "SubExpr" }
override int getPrecedence() { result = 13 }
}
@@ -241,7 +236,7 @@ class SubExpr extends BinaryArithmeticOperation, @subexpr {
class MulExpr extends BinaryArithmeticOperation, @mulexpr {
override string getOperator() { result = "*" }
override string getAPrimaryQlClass() { result = "MulExpr" }
override string getCanonicalQLClass() { result = "MulExpr" }
override int getPrecedence() { result = 14 }
}
@@ -255,7 +250,7 @@ class MulExpr extends BinaryArithmeticOperation, @mulexpr {
class DivExpr extends BinaryArithmeticOperation, @divexpr {
override string getOperator() { result = "/" }
override string getAPrimaryQlClass() { result = "DivExpr" }
override string getCanonicalQLClass() { result = "DivExpr" }
override int getPrecedence() { result = 14 }
}
@@ -269,7 +264,7 @@ class DivExpr extends BinaryArithmeticOperation, @divexpr {
class RemExpr extends BinaryArithmeticOperation, @remexpr {
override string getOperator() { result = "%" }
override string getAPrimaryQlClass() { result = "RemExpr" }
override string getCanonicalQLClass() { result = "RemExpr" }
override int getPrecedence() { result = 14 }
}
@@ -286,7 +281,7 @@ class RemExpr extends BinaryArithmeticOperation, @remexpr {
class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
override string getOperator() { result = "*" }
override string getAPrimaryQlClass() { result = "ImaginaryMulExpr" }
override string getCanonicalQLClass() { result = "ImaginaryMulExpr" }
override int getPrecedence() { result = 14 }
}
@@ -303,7 +298,7 @@ class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
override string getOperator() { result = "/" }
override string getAPrimaryQlClass() { result = "ImaginaryDivExpr" }
override string getCanonicalQLClass() { result = "ImaginaryDivExpr" }
override int getPrecedence() { result = 14 }
}
@@ -321,7 +316,7 @@ class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "RealImaginaryAddExpr" }
override string getCanonicalQLClass() { result = "RealImaginaryAddExpr" }
override int getPrecedence() { result = 13 }
}
@@ -339,7 +334,7 @@ class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "ImaginaryRealAddExpr" }
override string getCanonicalQLClass() { result = "ImaginaryRealAddExpr" }
override int getPrecedence() { result = 13 }
}
@@ -357,7 +352,7 @@ class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "RealImaginarySubExpr" }
override string getCanonicalQLClass() { result = "RealImaginarySubExpr" }
override int getPrecedence() { result = 13 }
}
@@ -375,7 +370,7 @@ class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "ImaginaryRealSubExpr" }
override string getCanonicalQLClass() { result = "ImaginaryRealSubExpr" }
override int getPrecedence() { result = 13 }
}
@@ -389,7 +384,7 @@ class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
class MinExpr extends BinaryArithmeticOperation, @minexpr {
override string getOperator() { result = "<?" }
override string getAPrimaryQlClass() { result = "MinExpr" }
override string getCanonicalQLClass() { result = "MinExpr" }
}
/**
@@ -401,7 +396,7 @@ class MinExpr extends BinaryArithmeticOperation, @minexpr {
class MaxExpr extends BinaryArithmeticOperation, @maxexpr {
override string getOperator() { result = ">?" }
override string getAPrimaryQlClass() { result = "MaxExpr" }
override string getCanonicalQLClass() { result = "MaxExpr" }
}
/**
@@ -419,7 +414,7 @@ class PointerArithmeticOperation extends BinaryArithmeticOperation, @p_arith_op_
class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
override string getOperator() { result = "+" }
override string getAPrimaryQlClass() { result = "PointerAddExpr" }
override string getCanonicalQLClass() { result = "PointerAddExpr" }
override int getPrecedence() { result = 13 }
}
@@ -434,7 +429,7 @@ class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "PointerSubExpr" }
override string getCanonicalQLClass() { result = "PointerSubExpr" }
override int getPrecedence() { result = 13 }
}
@@ -449,7 +444,7 @@ class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
class PointerDiffExpr extends PointerArithmeticOperation, @pdiffexpr {
override string getOperator() { result = "-" }
override string getAPrimaryQlClass() { result = "PointerDiffExpr" }
override string getCanonicalQLClass() { result = "PointerDiffExpr" }
override int getPrecedence() { result = 13 }
}

View File

@@ -38,7 +38,7 @@ class Assignment extends Operation, @assign_expr {
class AssignExpr extends Assignment, @assignexpr {
override string getOperator() { result = "=" }
override string getAPrimaryQlClass() { result = "AssignExpr" }
override string getCanonicalQLClass() { result = "AssignExpr" }
/** Gets a textual representation of this assignment. */
override string toString() { result = "... = ..." }
@@ -64,7 +64,7 @@ class AssignArithmeticOperation extends AssignOperation, @assign_arith_expr { }
* ```
*/
class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
override string getAPrimaryQlClass() { result = "AssignAddExpr" }
override string getCanonicalQLClass() { result = "AssignAddExpr" }
override string getOperator() { result = "+=" }
}
@@ -76,7 +76,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
* ```
*/
class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
override string getAPrimaryQlClass() { result = "AssignSubExpr" }
override string getCanonicalQLClass() { result = "AssignSubExpr" }
override string getOperator() { result = "-=" }
}
@@ -88,7 +88,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
* ```
*/
class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
override string getAPrimaryQlClass() { result = "AssignMulExpr" }
override string getCanonicalQLClass() { result = "AssignMulExpr" }
override string getOperator() { result = "*=" }
}
@@ -100,7 +100,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
* ```
*/
class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
override string getAPrimaryQlClass() { result = "AssignDivExpr" }
override string getCanonicalQLClass() { result = "AssignDivExpr" }
override string getOperator() { result = "/=" }
}
@@ -112,7 +112,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
* ```
*/
class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
override string getAPrimaryQlClass() { result = "AssignRemExpr" }
override string getCanonicalQLClass() { result = "AssignRemExpr" }
override string getOperator() { result = "%=" }
}
@@ -130,7 +130,7 @@ class AssignBitwiseOperation extends AssignOperation, @assign_bitwise_expr { }
* ```
*/
class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
override string getAPrimaryQlClass() { result = "AssignAndExpr" }
override string getCanonicalQLClass() { result = "AssignAndExpr" }
override string getOperator() { result = "&=" }
}
@@ -142,7 +142,7 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
* ```
*/
class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
override string getAPrimaryQlClass() { result = "AssignOrExpr" }
override string getCanonicalQLClass() { result = "AssignOrExpr" }
override string getOperator() { result = "|=" }
}
@@ -154,7 +154,7 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
* ```
*/
class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
override string getAPrimaryQlClass() { result = "AssignXorExpr" }
override string getCanonicalQLClass() { result = "AssignXorExpr" }
override string getOperator() { result = "^=" }
}
@@ -166,7 +166,7 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
* ```
*/
class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
override string getCanonicalQLClass() { result = "AssignLShiftExpr" }
override string getOperator() { result = "<<=" }
}
@@ -178,7 +178,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
* ```
*/
class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
override string getCanonicalQLClass() { result = "AssignRShiftExpr" }
override string getOperator() { result = ">>=" }
}
@@ -190,7 +190,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
* ```
*/
class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
override string getAPrimaryQlClass() { result = "AssignPointerAddExpr" }
override string getCanonicalQLClass() { result = "AssignPointerAddExpr" }
override string getOperator() { result = "+=" }
}
@@ -202,7 +202,7 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
* ```
*/
class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
override string getAPrimaryQlClass() { result = "AssignPointerSubExpr" }
override string getCanonicalQLClass() { result = "AssignPointerSubExpr" }
override string getOperator() { result = "-=" }
}
@@ -227,7 +227,7 @@ class ConditionDeclExpr extends Expr, @condition_decl {
*/
deprecated Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
override string getCanonicalQLClass() { result = "ConditionDeclExpr" }
/**
* Gets the compiler-generated variable access that conceptually occurs after

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling bitwise operations such as `~`, `<<`, `&` and
* `|`.
*/
import semmle.code.cpp.exprs.Expr
/**
@@ -21,7 +16,7 @@ class ComplementExpr extends UnaryBitwiseOperation, @complementexpr {
override int getPrecedence() { result = 16 }
override string getAPrimaryQlClass() { result = "ComplementExpr" }
override string getCanonicalQLClass() { result = "ComplementExpr" }
}
/**
@@ -40,7 +35,7 @@ class LShiftExpr extends BinaryBitwiseOperation, @lshiftexpr {
override int getPrecedence() { result = 12 }
override string getAPrimaryQlClass() { result = "LShiftExpr" }
override string getCanonicalQLClass() { result = "LShiftExpr" }
}
/**
@@ -54,7 +49,7 @@ class RShiftExpr extends BinaryBitwiseOperation, @rshiftexpr {
override int getPrecedence() { result = 12 }
override string getAPrimaryQlClass() { result = "RShiftExpr" }
override string getCanonicalQLClass() { result = "RShiftExpr" }
}
/**
@@ -68,7 +63,7 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @andexpr {
override int getPrecedence() { result = 8 }
override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
override string getCanonicalQLClass() { result = "BitwiseAndExpr" }
}
/**
@@ -82,7 +77,7 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @orexpr {
override int getPrecedence() { result = 6 }
override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
override string getCanonicalQLClass() { result = "BitwiseOrExpr" }
}
/**
@@ -96,5 +91,5 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, @xorexpr {
override int getPrecedence() { result = 7 }
override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
override string getCanonicalQLClass() { result = "BitwiseXorExpr" }
}

View File

@@ -1,16 +1,11 @@
/**
* Provides classes for modeling built-in operations. Built-in operations are
* typically compiler specific and are used by libraries and generated code.
*/
import semmle.code.cpp.exprs.Expr
/**
* A C/C++ built-in operation. This is the root QL class encompassing
* A C/C++ builtin operation. This is the root QL class encompassing
* built-in functionality.
*/
class BuiltInOperation extends Expr, @builtin_op {
override string getAPrimaryQlClass() { result = "BuiltInOperation" }
override string getCanonicalQLClass() { result = "BuiltInOperation" }
}
/**
@@ -30,7 +25,7 @@ class VarArgsExpr extends BuiltInOperation, @var_args_expr { }
class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
override string toString() { result = "__builtin_va_start" }
override string getAPrimaryQlClass() { result = "BuiltInVarArgsStart" }
override string getCanonicalQLClass() { result = "BuiltInVarArgsStart" }
/**
* Gets the `va_list` argument.
@@ -55,7 +50,7 @@ class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
override string toString() { result = "__builtin_va_end" }
override string getAPrimaryQlClass() { result = "BuiltInVarArgsEnd" }
override string getCanonicalQLClass() { result = "BuiltInVarArgsEnd" }
/**
* Gets the `va_list` argument.
@@ -73,7 +68,7 @@ class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
override string toString() { result = "__builtin_va_arg" }
override string getAPrimaryQlClass() { result = "BuiltInVarArg" }
override string getCanonicalQLClass() { result = "BuiltInVarArg" }
/**
* Gets the `va_list` argument.
@@ -93,7 +88,7 @@ class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
override string toString() { result = "__builtin_va_copy" }
override string getAPrimaryQlClass() { result = "BuiltInVarArgCopy" }
override string getCanonicalQLClass() { result = "BuiltInVarArgCopy" }
/**
* Gets the destination `va_list` argument.
@@ -115,7 +110,7 @@ class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
class BuiltInNoOp extends BuiltInOperation, @noopexpr {
override string toString() { result = "__noop" }
override string getAPrimaryQlClass() { result = "BuiltInNoOp" }
override string getCanonicalQLClass() { result = "BuiltInNoOp" }
}
/**
@@ -137,7 +132,7 @@ deprecated class BuiltInOperationOffsetOf = BuiltInOperationBuiltInOffsetOf;
class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
override string toString() { result = "__builtin_offsetof" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInOffsetOf" }
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInOffsetOf" }
}
/**
@@ -154,7 +149,7 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
override string toString() { result = "__INTADDR__" }
override string getAPrimaryQlClass() { result = "BuiltInIntAddr" }
override string getCanonicalQLClass() { result = "BuiltInIntAddr" }
}
/**
@@ -169,7 +164,7 @@ class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
override string toString() { result = "__has_assign" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasAssign" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasAssign" }
}
/**
@@ -184,7 +179,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
override string toString() { result = "__has_copy" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasCopy" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasCopy" }
}
/**
@@ -200,7 +195,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
override string toString() { result = "__has_nothrow_assign" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowAssign" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowAssign" }
}
/**
@@ -216,7 +211,7 @@ class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassi
class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothrowconstr {
override string toString() { result = "__has_nothrow_constructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowConstructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowConstructor" }
}
/**
@@ -231,7 +226,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
override string toString() { result = "__has_nothrow_copy" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNoThrowCopy" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasNoThrowCopy" }
}
/**
@@ -247,7 +242,7 @@ class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassign {
override string toString() { result = "__has_trivial_assign" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialAssign" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialAssign" }
}
/**
@@ -262,7 +257,7 @@ class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassi
class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivialconstr {
override string toString() { result = "__has_trivial_constructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialConstructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialConstructor" }
}
/**
@@ -277,7 +272,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
override string toString() { result = "__has_trivial_copy" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialCopy" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialCopy" }
}
/**
@@ -292,7 +287,7 @@ class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivialdestructor {
override string toString() { result = "__has_trivial_destructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialDestructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialDestructor" }
}
/**
@@ -307,7 +302,7 @@ class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivial
class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr {
override string toString() { result = "__has_user_destructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUserDestructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasUserDestructor" }
}
/**
@@ -325,7 +320,7 @@ class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr
class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtualdestr {
override string toString() { result = "__has_virtual_destructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasVirtualDestructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasVirtualDestructor" }
}
/**
@@ -340,7 +335,7 @@ class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtual
class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
override string toString() { result = "__is_abstract" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAbstract" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsAbstract" }
}
/**
@@ -355,7 +350,7 @@ class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
override string toString() { result = "__is_base_of" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsBaseOf" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsBaseOf" }
}
/**
@@ -370,7 +365,7 @@ class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
override string toString() { result = "__is_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsClass" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsClass" }
}
/**
@@ -385,7 +380,7 @@ class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
override string toString() { result = "__is_convertible_to" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConvertibleTo" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsConvertibleTo" }
}
/**
@@ -400,7 +395,7 @@ class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
override string toString() { result = "__is_empty" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsEmpty" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsEmpty" }
}
/**
@@ -415,7 +410,7 @@ class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
override string toString() { result = "__is_enum" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsEnum" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsEnum" }
}
/**
@@ -432,7 +427,7 @@ class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
override string toString() { result = "__is_pod" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsPod" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsPod" }
}
/**
@@ -447,7 +442,7 @@ class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
override string toString() { result = "__is_polymorphic" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsPolymorphic" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsPolymorphic" }
}
/**
@@ -462,7 +457,7 @@ class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
override string toString() { result = "__is_union" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnion" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsUnion" }
}
/**
@@ -501,7 +496,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshufflevector {
override string toString() { result = "__builtin_shufflevector" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInShuffleVector" }
}
/**
@@ -521,7 +516,7 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
class BuiltInOperationBuiltInConvertVector extends BuiltInOperation, @builtinconvertvector {
override string toString() { result = "__builtin_convertvector" }
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInConvertVector" }
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInConvertVector" }
}
/**
@@ -543,7 +538,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
result = this.getOperand().(ReferenceDereferenceExpr).getChild(0).(Access).getTarget()
}
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInAddressOf" }
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInAddressOf" }
override string getOperator() { result = "__builtin_addressof" }
}
@@ -565,7 +560,7 @@ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
@istriviallyconstructibleexpr {
override string toString() { result = "__is_trivially_constructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyConstructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyConstructible" }
}
/**
@@ -582,7 +577,7 @@ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleexpr {
override string toString() { result = "__is_destructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsDestructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsDestructible" }
}
/**
@@ -599,7 +594,7 @@ class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleex
class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrowdestructibleexpr {
override string toString() { result = "__is_nothrow_destructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowDestructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowDestructible" }
}
/**
@@ -615,7 +610,7 @@ class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrow
class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr {
override string toString() { result = "__is_trivially_destructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyDestructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyDestructible" }
}
/**
@@ -634,7 +629,7 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
override string toString() { result = "__is_trivially_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyAssignable" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyAssignable" }
}
/**
@@ -650,7 +645,7 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
override string toString() { result = "__is_nothrow_assignable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowAssignable" }
}
/**
@@ -670,7 +665,7 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayoutexpr {
override string toString() { result = "__is_standard_layout" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsStandardLayout" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsStandardLayout" }
}
/**
@@ -684,7 +679,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
override string toString() { result = "__is_trivially_copyable" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyCopyable" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsTriviallyCopyable" }
}
/**
@@ -704,7 +699,7 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
override string toString() { result = "__is_literal_type" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsLiteralType" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsLiteralType" }
}
/**
@@ -722,7 +717,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@hastrivialmoveconstructorexpr {
override string toString() { result = "__has_trivial_move_constructor" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveConstructor" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialMoveConstructor" }
}
/**
@@ -740,7 +735,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivialmoveassignexpr {
override string toString() { result = "__has_trivial_move_assign" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveAssign" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasTrivialMoveAssign" }
}
/**
@@ -756,7 +751,7 @@ class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivial
class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrowmoveassignexpr {
override string toString() { result = "__has_nothrow_move_assign" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasNothrowMoveAssign" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasNothrowMoveAssign" }
}
/**
@@ -775,7 +770,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructibleexpr {
override string toString() { result = "__is_constructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsConstructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsConstructible" }
}
/**
@@ -791,7 +786,7 @@ class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructible
class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothrowconstructibleexpr {
override string toString() { result = "__is_nothrow_constructible" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowConstructible" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsNothrowConstructible" }
}
/**
@@ -806,7 +801,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
override string toString() { result = "__has_finalizer" }
override string getAPrimaryQlClass() { result = "BuiltInOperationHasFinalizer" }
override string getCanonicalQLClass() { result = "BuiltInOperationHasFinalizer" }
}
/**
@@ -820,7 +815,7 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
override string toString() { result = "__is_delegate" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsDelegate" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsDelegate" }
}
/**
@@ -833,7 +828,7 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfaceclassexpr {
override string toString() { result = "__is_interface_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsInterfaceClass" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsInterfaceClass" }
}
/**
@@ -850,7 +845,7 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
override string toString() { result = "__is_ref_array" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsRefArray" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsRefArray" }
}
/**
@@ -867,7 +862,7 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
override string toString() { result = "__is_ref_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsRefClass" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsRefClass" }
}
/**
@@ -885,7 +880,7 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
override string toString() { result = "__is_sealed" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSealed" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsSealed" }
}
/**
@@ -904,7 +899,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalueclassexpr {
override string toString() { result = "__is_simple_value_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsSimpleValueClass" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsSimpleValueClass" }
}
/**
@@ -921,7 +916,7 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
override string toString() { result = "__is_value_class" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsValueClass" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsValueClass" }
}
/**
@@ -939,7 +934,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
override string toString() { result = "__is_final" }
override string getAPrimaryQlClass() { result = "BuiltInOperationIsFinal" }
override string getCanonicalQLClass() { result = "BuiltInOperationIsFinal" }
}
/**
@@ -954,7 +949,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
class BuiltInChooseExpr extends BuiltInOperation, @builtinchooseexpr {
override string toString() { result = "__builtin_choose_expr" }
override string getAPrimaryQlClass() { result = "BuiltInChooseExpr" }
override string getCanonicalQLClass() { result = "BuiltInChooseExpr" }
}
/**
@@ -971,7 +966,7 @@ class BuiltInChooseExpr extends BuiltInOperation, @builtinchooseexpr {
class VectorFillOperation extends UnaryOperation, @vec_fill {
override string getOperator() { result = "(vector fill)" }
override string getAPrimaryQlClass() { result = "VectorFillOperation" }
override string getCanonicalQLClass() { result = "VectorFillOperation" }
}
/**
@@ -980,7 +975,7 @@ class VectorFillOperation extends UnaryOperation, @vec_fill {
class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
override string toString() { result = "__builtin_complex" }
override string getAPrimaryQlClass() { result = "BuiltInComplexOperation" }
override string getCanonicalQLClass() { result = "BuiltInComplexOperation" }
/** Gets the operand corresponding to the real part of the complex number. */
Expr getRealOperand() { this.hasChild(result, 0) }

View File

@@ -1,29 +1,13 @@
/**
* Provides classes for modeling call expressions including direct calls to
* functions, constructor and destructor calls, and calls made through function
* pointers.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.Function
private import semmle.code.cpp.dataflow.EscapesTree
private class TCall = @funbindexpr or @callexpr;
/**
* A C/C++ call.
*
* This is the abstract root QL class for all types of calls.
*/
class Call extends Expr, NameQualifiableElement, TCall {
// `@funbindexpr` (which is the dbscheme type for FunctionCall) is a union type that includes
// `@routineexpr. This dbscheme type includes accesses to functions that are not necessarily calls to
// that function. That's why the charpred for `FunctionCall` requires:
// ```
// iscall(underlyingElement(this), _)
// ```
// So for the charpred for `Call` we include the requirement that if this is an instance of
// `@funbindexpr` it must be a _call_ to the function.
Call() { this instanceof @callexpr or iscall(underlyingElement(this), _) }
abstract class Call extends Expr, NameQualifiableElement {
/**
* Gets the number of arguments (actual parameters) of this call. The count
* does _not_ include the qualifier of the call, if any.
@@ -90,7 +74,7 @@ class Call extends Expr, NameQualifiableElement, TCall {
* method, and it might not exist.
* - For a variable call, it never exists.
*/
Function getTarget() { none() } // overridden in subclasses
abstract Function getTarget();
override int getPrecedence() { result = 17 }
@@ -164,7 +148,7 @@ class Call extends Expr, NameQualifiableElement, TCall {
class FunctionCall extends Call, @funbindexpr {
FunctionCall() { iscall(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "FunctionCall" }
override string getCanonicalQLClass() { result = "FunctionCall" }
/** Gets an explicit template argument for this call. */
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
@@ -313,7 +297,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
getTarget().getEffectiveNumberOfParameters() = 1
}
override string getAPrimaryQlClass() { result = "OverloadedPointerDereferenceExpr" }
override string getCanonicalQLClass() { result = "OverloadedPointerDereferenceExpr" }
/**
* Gets the expression this operator * applies to.
@@ -361,7 +345,7 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
class OverloadedArrayExpr extends FunctionCall {
OverloadedArrayExpr() { getTarget().hasName("operator[]") }
override string getAPrimaryQlClass() { result = "OverloadedArrayExpr" }
override string getCanonicalQLClass() { result = "OverloadedArrayExpr" }
/**
* Gets the expression being subscripted.
@@ -393,7 +377,7 @@ class ExprCall extends Call, @callexpr {
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ExprCall" }
override string getCanonicalQLClass() { result = "ExprCall" }
override Expr getAnArgument() { exists(int i | result = this.getChild(i) and i >= 1) }
@@ -417,7 +401,7 @@ class ExprCall extends Call, @callexpr {
class VariableCall extends ExprCall {
VariableCall() { this.getExpr() instanceof VariableAccess }
override string getAPrimaryQlClass() { result = "VariableCall" }
override string getCanonicalQLClass() { result = "VariableCall" }
/**
* Gets the variable which yields the function pointer to call.
@@ -435,7 +419,7 @@ class VariableCall extends ExprCall {
class ConstructorCall extends FunctionCall {
ConstructorCall() { super.getTarget() instanceof Constructor }
override string getAPrimaryQlClass() { result = "ConstructorCall" }
override string getCanonicalQLClass() { result = "ConstructorCall" }
/** Gets the constructor being called. */
override Constructor getTarget() { result = super.getTarget() }
@@ -454,7 +438,7 @@ class ThrowExpr extends Expr, @throw_expr {
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
override string getCanonicalQLClass() { result = "ThrowExpr" }
override string toString() { result = "throw ..." }
@@ -470,7 +454,7 @@ class ThrowExpr extends Expr, @throw_expr {
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
override string getCanonicalQLClass() { result = "ReThrowExpr" }
override string toString() { result = "re-throw exception " }
}
@@ -485,7 +469,7 @@ class ReThrowExpr extends ThrowExpr {
class DestructorCall extends FunctionCall {
DestructorCall() { super.getTarget() instanceof Destructor }
override string getAPrimaryQlClass() { result = "DestructorCall" }
override string getCanonicalQLClass() { result = "DestructorCall" }
/** Gets the destructor being called. */
override Destructor getTarget() { result = super.getTarget() }
@@ -509,7 +493,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
*/
Expr getQualifier() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "VacuousDestructorCall" }
override string getCanonicalQLClass() { result = "VacuousDestructorCall" }
override string toString() { result = "(vacuous destructor call)" }
}
@@ -522,7 +506,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
* initializations.
*/
class ConstructorInit extends Expr, @ctorinit {
override string getAPrimaryQlClass() { result = "ConstructorInit" }
override string getCanonicalQLClass() { result = "ConstructorInit" }
}
/**
@@ -530,7 +514,7 @@ class ConstructorInit extends Expr, @ctorinit {
* initializer list or compiler-generated actions.
*/
class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
override string getAPrimaryQlClass() { result = "ConstructorBaseInit" }
override string getCanonicalQLClass() { result = "ConstructorBaseInit" }
}
/**
@@ -547,7 +531,7 @@ class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
* ```
*/
class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
override string getAPrimaryQlClass() { result = "ConstructorDirectInit" }
override string getCanonicalQLClass() { result = "ConstructorDirectInit" }
}
/**
@@ -567,7 +551,7 @@ class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
* ```
*/
class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
override string getAPrimaryQlClass() { result = "ConstructorVirtualInit" }
override string getCanonicalQLClass() { result = "ConstructorVirtualInit" }
}
/**
@@ -582,7 +566,7 @@ class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
* ```
*/
class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit {
override string getAPrimaryQlClass() { result = "ConstructorDelegationInit" }
override string getCanonicalQLClass() { result = "ConstructorDelegationInit" }
}
/**
@@ -601,7 +585,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
/** Gets the field being initialized. */
Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) }
override string getAPrimaryQlClass() { result = "ConstructorFieldInit" }
override string getCanonicalQLClass() { result = "ConstructorFieldInit" }
/**
* Gets the expression to which the field is initialized.
@@ -623,7 +607,7 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
* compiler-generated actions.
*/
class DestructorDestruction extends Expr, @dtordestruct {
override string getAPrimaryQlClass() { result = "DestructorDestruction" }
override string getCanonicalQLClass() { result = "DestructorDestruction" }
}
/**
@@ -631,7 +615,7 @@ class DestructorDestruction extends Expr, @dtordestruct {
* compiler-generated actions.
*/
class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
override string getAPrimaryQlClass() { result = "DestructorBaseDestruction" }
override string getCanonicalQLClass() { result = "DestructorBaseDestruction" }
}
/**
@@ -645,7 +629,7 @@ class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
* ```
*/
class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirectdestruct {
override string getAPrimaryQlClass() { result = "DestructorDirectDestruction" }
override string getCanonicalQLClass() { result = "DestructorDirectDestruction" }
}
/**
@@ -662,7 +646,7 @@ class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirect
* ```
*/
class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtualdestruct {
override string getAPrimaryQlClass() { result = "DestructorVirtualDestruction" }
override string getCanonicalQLClass() { result = "DestructorVirtualDestruction" }
}
/**
@@ -680,7 +664,7 @@ class DestructorFieldDestruction extends DestructorDestruction, @dtorfielddestru
/** Gets the field being destructed. */
Field getTarget() { varbind(underlyingElement(this), unresolveElement(result)) }
override string getAPrimaryQlClass() { result = "DestructorFieldDestruction" }
override string getCanonicalQLClass() { result = "DestructorFieldDestruction" }
/** Gets the compiler-generated call to the variable's destructor. */
DestructorCall getExpr() { result = this.getChild(0) }

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling C/C++ casts and conversions, as well as some
* type-related operators such as `sizeof` and `alignof`.
*/
import semmle.code.cpp.exprs.Expr
private import semmle.code.cpp.internal.ResolveClass
@@ -97,7 +92,7 @@ module CastConsistency {
class CStyleCast extends Cast, @c_style_cast {
override string toString() { result = "(" + this.getType().getName() + ")..." }
override string getAPrimaryQlClass() { result = "CStyleCast" }
override string getCanonicalQLClass() { result = "CStyleCast" }
override int getPrecedence() { result = 16 }
}
@@ -116,7 +111,7 @@ class CStyleCast extends Cast, @c_style_cast {
class StaticCast extends Cast, @static_cast {
override string toString() { result = "static_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "StaticCast" }
override string getCanonicalQLClass() { result = "StaticCast" }
override int getPrecedence() { result = 17 }
}
@@ -134,7 +129,7 @@ class StaticCast extends Cast, @static_cast {
class ConstCast extends Cast, @const_cast {
override string toString() { result = "const_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "ConstCast" }
override string getCanonicalQLClass() { result = "ConstCast" }
override int getPrecedence() { result = 17 }
}
@@ -152,7 +147,7 @@ class ConstCast extends Cast, @const_cast {
class ReinterpretCast extends Cast, @reinterpret_cast {
override string toString() { result = "reinterpret_cast<" + this.getType().getName() + ">..." }
override string getAPrimaryQlClass() { result = "ReinterpretCast" }
override string getCanonicalQLClass() { result = "ReinterpretCast" }
override int getPrecedence() { result = 17 }
}
@@ -208,7 +203,7 @@ class IntegralConversion extends ArithmeticConversion {
isIntegralOrEnum(getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "IntegralConversion"
}
@@ -228,7 +223,7 @@ class FloatingPointConversion extends ArithmeticConversion {
getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "FloatingPointConversion"
}
@@ -248,7 +243,7 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
getExpr().getUnspecifiedType() instanceof FloatingPointType
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "FloatingPointToIntegralConversion"
}
@@ -268,7 +263,7 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
isIntegralOrEnum(getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "IntegralToFloatingPointConversion"
}
@@ -294,7 +289,9 @@ class PointerConversion extends Cast {
isPointerOrNullPointer(getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "PointerConversion" }
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PointerConversion"
}
override string getSemanticConversionString() { result = "pointer conversion" }
}
@@ -328,7 +325,7 @@ class PointerToMemberConversion extends Cast {
)
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PointerToMemberConversion"
}
@@ -349,7 +346,7 @@ class PointerToIntegralConversion extends Cast {
isPointerOrNullPointer(getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PointerToIntegralConversion"
}
@@ -370,7 +367,7 @@ class IntegralToPointerConversion extends Cast {
isIntegralOrEnum(getExpr().getUnspecifiedType())
}
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "IntegralToPointerConversion"
}
@@ -388,7 +385,7 @@ class IntegralToPointerConversion extends Cast {
class BoolConversion extends Cast {
BoolConversion() { conversionkinds(underlyingElement(this), 1) }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "BoolConversion" }
override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "BoolConversion" }
override string getSemanticConversionString() { result = "conversion to bool" }
}
@@ -406,7 +403,7 @@ class VoidConversion extends Cast {
getUnspecifiedType() instanceof VoidType
}
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "VoidConversion" }
override string getCanonicalQLClass() { not exists(qlCast(this)) and result = "VoidConversion" }
override string getSemanticConversionString() { result = "conversion to void" }
}
@@ -482,7 +479,7 @@ private Class getConversionClass(Expr expr) {
class BaseClassConversion extends InheritanceConversion {
BaseClassConversion() { conversionkinds(underlyingElement(this), 2) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "BaseClassConversion"
}
@@ -509,7 +506,7 @@ class BaseClassConversion extends InheritanceConversion {
class DerivedClassConversion extends InheritanceConversion {
DerivedClassConversion() { conversionkinds(underlyingElement(this), 3) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "DerivedClassConversion"
}
@@ -531,7 +528,7 @@ class DerivedClassConversion extends InheritanceConversion {
class PointerToMemberBaseClassConversion extends Cast {
PointerToMemberBaseClassConversion() { conversionkinds(underlyingElement(this), 4) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PointerToMemberBaseClassConversion"
}
@@ -551,7 +548,7 @@ class PointerToMemberBaseClassConversion extends Cast {
class PointerToMemberDerivedClassConversion extends Cast {
PointerToMemberDerivedClassConversion() { conversionkinds(underlyingElement(this), 5) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PointerToMemberDerivedClassConversion"
}
@@ -572,7 +569,9 @@ class PointerToMemberDerivedClassConversion extends Cast {
class GlvalueConversion extends Cast {
GlvalueConversion() { conversionkinds(underlyingElement(this), 6) }
override string getAPrimaryQlClass() { not exists(qlCast(this)) and result = "GlvalueConversion" }
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "GlvalueConversion"
}
override string getSemanticConversionString() { result = "glvalue conversion" }
}
@@ -598,7 +597,7 @@ class GlvalueConversion extends Cast {
class PrvalueAdjustmentConversion extends Cast {
PrvalueAdjustmentConversion() { conversionkinds(underlyingElement(this), 7) }
override string getAPrimaryQlClass() {
override string getCanonicalQLClass() {
not exists(qlCast(this)) and result = "PrvalueAdjustmentConversion"
}
@@ -621,7 +620,7 @@ class DynamicCast extends Cast, @dynamic_cast {
override int getPrecedence() { result = 17 }
override string getAPrimaryQlClass() { result = "DynamicCast" }
override string getCanonicalQLClass() { result = "DynamicCast" }
override string getSemanticConversionString() { result = "dynamic_cast" }
}
@@ -661,9 +660,6 @@ class UuidofOperator extends Expr, @uuidof {
* ```
*/
class TypeidOperator extends Expr, @type_id {
/**
* Gets the type that is returned by this typeid expression.
*/
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
/**
@@ -673,7 +669,7 @@ class TypeidOperator extends Expr, @type_id {
*/
deprecated Type getSpecifiedType() { result = this.getResultType() }
override string getAPrimaryQlClass() { result = "TypeidOperator" }
override string getCanonicalQLClass() { result = "TypeidOperator" }
/**
* Gets the contained expression, if any (if this typeid contains
@@ -703,7 +699,7 @@ class TypeidOperator extends Expr, @type_id {
class SizeofPackOperator extends Expr, @sizeof_pack {
override string toString() { result = "sizeof...(...)" }
override string getAPrimaryQlClass() { result = "SizeofPackOperator" }
override string getCanonicalQLClass() { result = "SizeofPackOperator" }
override predicate mayBeImpure() { none() }
@@ -726,7 +722,7 @@ class SizeofOperator extends Expr, @runtime_sizeof {
class SizeofExprOperator extends SizeofOperator {
SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) }
override string getAPrimaryQlClass() { result = "SizeofExprOperator" }
override string getCanonicalQLClass() { result = "SizeofExprOperator" }
/** Gets the contained expression. */
Expr getExprOperand() { result = this.getChild(0) }
@@ -754,7 +750,7 @@ class SizeofExprOperator extends SizeofOperator {
class SizeofTypeOperator extends SizeofOperator {
SizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
override string getAPrimaryQlClass() { result = "SizeofTypeOperator" }
override string getCanonicalQLClass() { result = "SizeofTypeOperator" }
/** Gets the contained type. */
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
@@ -833,7 +829,7 @@ class ArrayToPointerConversion extends Conversion, @array_to_pointer {
/** Gets a textual representation of this conversion. */
override string toString() { result = "array to pointer conversion" }
override string getAPrimaryQlClass() { result = "ArrayToPointerConversion" }
override string getCanonicalQLClass() { result = "ArrayToPointerConversion" }
override predicate mayBeImpure() { none() }

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling comparisons such as `==`, `!=` and `<`.
*/
import semmle.code.cpp.exprs.Expr
/**
@@ -25,7 +21,7 @@ class EqualityOperation extends ComparisonOperation, @eq_op_expr {
* ```
*/
class EQExpr extends EqualityOperation, @eqexpr {
override string getAPrimaryQlClass() { result = "EQExpr" }
override string getCanonicalQLClass() { result = "EQExpr" }
override string getOperator() { result = "==" }
}
@@ -37,7 +33,7 @@ class EQExpr extends EqualityOperation, @eqexpr {
* ```
*/
class NEExpr extends EqualityOperation, @neexpr {
override string getAPrimaryQlClass() { result = "NEExpr" }
override string getCanonicalQLClass() { result = "NEExpr" }
override string getOperator() { result = "!=" }
}
@@ -82,7 +78,7 @@ class RelationalOperation extends ComparisonOperation, @rel_op_expr {
* ```
*/
class GTExpr extends RelationalOperation, @gtexpr {
override string getAPrimaryQlClass() { result = "GTExpr" }
override string getCanonicalQLClass() { result = "GTExpr" }
override string getOperator() { result = ">" }
@@ -98,7 +94,7 @@ class GTExpr extends RelationalOperation, @gtexpr {
* ```
*/
class LTExpr extends RelationalOperation, @ltexpr {
override string getAPrimaryQlClass() { result = "LTExpr" }
override string getCanonicalQLClass() { result = "LTExpr" }
override string getOperator() { result = "<" }
@@ -114,7 +110,7 @@ class LTExpr extends RelationalOperation, @ltexpr {
* ```
*/
class GEExpr extends RelationalOperation, @geexpr {
override string getAPrimaryQlClass() { result = "GEExpr" }
override string getCanonicalQLClass() { result = "GEExpr" }
override string getOperator() { result = ">=" }
@@ -130,7 +126,7 @@ class GEExpr extends RelationalOperation, @geexpr {
* ```
*/
class LEExpr extends RelationalOperation, @leexpr {
override string getAPrimaryQlClass() { result = "LEExpr" }
override string getCanonicalQLClass() { result = "LEExpr" }
override string getOperator() { result = "<=" }

View File

@@ -1,7 +1,3 @@
/**
* Provides classes modeling C/C++ expressions.
*/
import semmle.code.cpp.Element
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
@@ -569,7 +565,7 @@ class BinaryOperation extends Operation, @bin_op_expr {
class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
override string toString() { result = "({...})" }
override string getAPrimaryQlClass() { result = "ParenthesizedBracedInitializerList" }
override string getCanonicalQLClass() { result = "ParenthesizedBracedInitializerList" }
}
/**
@@ -584,7 +580,7 @@ class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
class ParenthesisExpr extends Conversion, @parexpr {
override string toString() { result = "(...)" }
override string getAPrimaryQlClass() { result = "ParenthesisExpr" }
override string getCanonicalQLClass() { result = "ParenthesisExpr" }
}
/**
@@ -595,7 +591,7 @@ class ParenthesisExpr extends Conversion, @parexpr {
class ErrorExpr extends Expr, @errorexpr {
override string toString() { result = "<error expr>" }
override string getAPrimaryQlClass() { result = "ErrorExpr" }
override string getCanonicalQLClass() { result = "ErrorExpr" }
}
/**
@@ -610,7 +606,7 @@ class ErrorExpr extends Expr, @errorexpr {
class AssumeExpr extends Expr, @assume {
override string toString() { result = "__assume(...)" }
override string getAPrimaryQlClass() { result = "AssumeExpr" }
override string getCanonicalQLClass() { result = "AssumeExpr" }
/**
* Gets the operand of the `__assume` expressions.
@@ -625,7 +621,7 @@ class AssumeExpr extends Expr, @assume {
* ```
*/
class CommaExpr extends Expr, @commaexpr {
override string getAPrimaryQlClass() { result = "CommaExpr" }
override string getCanonicalQLClass() { result = "CommaExpr" }
/**
* Gets the left operand, which is the one whose value is discarded.
@@ -660,7 +656,7 @@ class CommaExpr extends Expr, @commaexpr {
* ```
*/
class AddressOfExpr extends UnaryOperation, @address_of {
override string getAPrimaryQlClass() { result = "AddressOfExpr" }
override string getCanonicalQLClass() { result = "AddressOfExpr" }
/** Gets the function or variable whose address is taken. */
Declaration getAddressable() {
@@ -692,7 +688,7 @@ class AddressOfExpr extends UnaryOperation, @address_of {
class ReferenceToExpr extends Conversion, @reference_to {
override string toString() { result = "(reference to)" }
override string getAPrimaryQlClass() { result = "ReferenceToExpr" }
override string getCanonicalQLClass() { result = "ReferenceToExpr" }
override int getPrecedence() { result = 16 }
}
@@ -706,7 +702,7 @@ class ReferenceToExpr extends Conversion, @reference_to {
* ```
*/
class PointerDereferenceExpr extends UnaryOperation, @indirect {
override string getAPrimaryQlClass() { result = "PointerDereferenceExpr" }
override string getCanonicalQLClass() { result = "PointerDereferenceExpr" }
/**
* DEPRECATED: Use getOperand() instead.
@@ -744,7 +740,7 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
class ReferenceDereferenceExpr extends Conversion, @ref_indirect {
override string toString() { result = "(reference dereference)" }
override string getAPrimaryQlClass() { result = "ReferenceDereferenceExpr" }
override string getCanonicalQLClass() { result = "ReferenceDereferenceExpr" }
}
/**
@@ -850,7 +846,7 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
class NewExpr extends NewOrNewArrayExpr, @new_expr {
override string toString() { result = "new" }
override string getAPrimaryQlClass() { result = "NewExpr" }
override string getCanonicalQLClass() { result = "NewExpr" }
/**
* Gets the type that is being allocated.
@@ -880,7 +876,7 @@ class NewExpr extends NewOrNewArrayExpr, @new_expr {
class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
override string toString() { result = "new[]" }
override string getAPrimaryQlClass() { result = "NewArrayExpr" }
override string getCanonicalQLClass() { result = "NewArrayExpr" }
/**
* Gets the type that is being allocated.
@@ -928,7 +924,7 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
class DeleteExpr extends Expr, @delete_expr {
override string toString() { result = "delete" }
override string getAPrimaryQlClass() { result = "DeleteExpr" }
override string getCanonicalQLClass() { result = "DeleteExpr" }
override int getPrecedence() { result = 16 }
@@ -1002,7 +998,7 @@ class DeleteExpr extends Expr, @delete_expr {
class DeleteArrayExpr extends Expr, @delete_array_expr {
override string toString() { result = "delete[]" }
override string getAPrimaryQlClass() { result = "DeleteArrayExpr" }
override string getCanonicalQLClass() { result = "DeleteArrayExpr" }
override int getPrecedence() { result = 16 }
@@ -1082,7 +1078,7 @@ class StmtExpr extends Expr, @expr_stmt {
*/
Stmt getStmt() { result.getParent() = this }
override string getAPrimaryQlClass() { result = "StmtExpr" }
override string getCanonicalQLClass() { result = "StmtExpr" }
/**
* Gets the result expression of the enclosed statement. For example,
@@ -1107,7 +1103,7 @@ private Expr getStmtResultExpr(Stmt stmt) {
class ThisExpr extends Expr, @thisaccess {
override string toString() { result = "this" }
override string getAPrimaryQlClass() { result = "ThisExpr" }
override string getCanonicalQLClass() { result = "ThisExpr" }
override predicate mayBeImpure() { none() }
@@ -1143,7 +1139,7 @@ class BlockExpr extends Literal {
class NoExceptExpr extends Expr, @noexceptexpr {
override string toString() { result = "noexcept(...)" }
override string getAPrimaryQlClass() { result = "NoExceptExpr" }
override string getCanonicalQLClass() { result = "NoExceptExpr" }
/**
* Gets the expression inside this noexcept expression.
@@ -1175,7 +1171,7 @@ class FoldExpr extends Expr, @foldexpr {
)
}
override string getAPrimaryQlClass() { result = "FoldExpr" }
override string getCanonicalQLClass() { result = "FoldExpr" }
/** Gets the binary operator used in this fold expression, as a string. */
string getOperatorString() { fold(underlyingElement(this), result, _) }
@@ -1251,7 +1247,7 @@ private predicate constantTemplateLiteral(Expr e) {
* ```
*/
class SpaceshipExpr extends BinaryOperation, @spaceshipexpr {
override string getAPrimaryQlClass() { result = "SpaceshipExpr" }
override string getCanonicalQLClass() { result = "SpaceshipExpr" }
override int getPrecedence() { result = 11 }

View File

@@ -1,7 +1,3 @@
/**
* Provides classes for modeling lambda expressions and their captures.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.Class
@@ -19,7 +15,7 @@ import semmle.code.cpp.Class
class LambdaExpression extends Expr, @lambdaexpr {
override string toString() { result = "[...](...){...}" }
override string getAPrimaryQlClass() { result = "LambdaExpression" }
override string getCanonicalQLClass() { result = "LambdaExpression" }
/**
* Gets an implicitly or explicitly captured value of this lambda expression.
@@ -79,7 +75,7 @@ class LambdaExpression extends Expr, @lambdaexpr {
class Closure extends Class {
Closure() { exists(LambdaExpression e | this = e.getType()) }
override string getAPrimaryQlClass() { result = "Closure" }
override string getCanonicalQLClass() { result = "Closure" }
/** Gets the lambda expression of which this is the type. */
LambdaExpression getLambdaExpression() { result.getType() = this }
@@ -105,7 +101,7 @@ class Closure extends Class {
class LambdaCapture extends Locatable, @lambdacapture {
override string toString() { result = getField().getName() }
override string getAPrimaryQlClass() { result = "LambdaCapture" }
override string getCanonicalQLClass() { result = "LambdaCapture" }
/**
* Holds if this capture was made implicitly.

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling literals in the source code such as `0`, `'c'`
* or `"string"`.
*/
import semmle.code.cpp.exprs.Expr
/**
@@ -19,7 +14,7 @@ class Literal extends Expr, @literal {
result = "Unknown literal"
}
override string getAPrimaryQlClass() { result = "Literal" }
override string getCanonicalQLClass() { result = "Literal" }
override predicate mayBeImpure() { none() }
@@ -40,7 +35,7 @@ class Literal extends Expr, @literal {
class LabelLiteral extends Literal {
LabelLiteral() { jumpinfo(underlyingElement(this), _, _) }
override string getAPrimaryQlClass() { result = "LabelLiteral" }
override string getCanonicalQLClass() { result = "LabelLiteral" }
/** Gets the corresponding label statement. */
LabelStmt getLabel() { jumpinfo(underlyingElement(this), _, unresolveElement(result)) }
@@ -98,7 +93,7 @@ abstract class TextLiteral extends Literal {
class CharLiteral extends TextLiteral {
CharLiteral() { this.getValueText().regexpMatch("(?s)\\s*L?'.*") }
override string getAPrimaryQlClass() { result = "CharLiteral" }
override string getCanonicalQLClass() { result = "CharLiteral" }
/**
* Gets the character of this literal. For example `L'a'` has character `"a"`.
@@ -120,7 +115,7 @@ class StringLiteral extends TextLiteral {
// @aggregateliteral rather than @literal.
}
override string getAPrimaryQlClass() { result = "StringLiteral" }
override string getCanonicalQLClass() { result = "StringLiteral" }
}
/**
@@ -133,7 +128,7 @@ class StringLiteral extends TextLiteral {
class OctalLiteral extends Literal {
OctalLiteral() { super.getValueText().regexpMatch("\\s*0[0-7]+[uUlL]*\\s*") }
override string getAPrimaryQlClass() { result = "OctalLiteral" }
override string getCanonicalQLClass() { result = "OctalLiteral" }
}
/**
@@ -145,14 +140,14 @@ class OctalLiteral extends Literal {
class HexLiteral extends Literal {
HexLiteral() { super.getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F]+[uUlL]*\\s*") }
override string getAPrimaryQlClass() { result = "HexLiteral" }
override string getCanonicalQLClass() { result = "HexLiteral" }
}
/**
* A C/C++ aggregate literal.
*/
class AggregateLiteral extends Expr, @aggregateliteral {
override string getAPrimaryQlClass() { result = "AggregateLiteral" }
override string getCanonicalQLClass() { result = "AggregateLiteral" }
/**
* DEPRECATED: Use ClassAggregateLiteral.getFieldExpr() instead.
@@ -184,7 +179,7 @@ class ClassAggregateLiteral extends AggregateLiteral {
ClassAggregateLiteral() { classType = this.getUnspecifiedType() }
override string getAPrimaryQlClass() { result = "ClassAggregateLiteral" }
override string getCanonicalQLClass() { result = "ClassAggregateLiteral" }
/**
* Gets the expression within the aggregate literal that is used to initialize
@@ -304,7 +299,7 @@ class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral {
ArrayAggregateLiteral() { arrayType = this.getUnspecifiedType() }
override string getAPrimaryQlClass() { result = "ArrayAggregateLiteral" }
override string getCanonicalQLClass() { result = "ArrayAggregateLiteral" }
override int getArraySize() { result = arrayType.getArraySize() }
@@ -328,7 +323,7 @@ class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral {
VectorAggregateLiteral() { vectorType = this.getUnspecifiedType() }
override string getAPrimaryQlClass() { result = "VectorAggregateLiteral" }
override string getCanonicalQLClass() { result = "VectorAggregateLiteral" }
override int getArraySize() { result = vectorType.getNumElements() }

View File

@@ -1,8 +1,3 @@
/**
* Provides classes for modeling logical operations such as `!`, `&&`, `||`, and
* the ternary `? :` expression.
*/
import semmle.code.cpp.exprs.Expr
/**
@@ -19,7 +14,7 @@ class UnaryLogicalOperation extends UnaryOperation, @un_log_op_expr { }
class NotExpr extends UnaryLogicalOperation, @notexpr {
override string getOperator() { result = "!" }
override string getAPrimaryQlClass() { result = "NotExpr" }
override string getCanonicalQLClass() { result = "NotExpr" }
override int getPrecedence() { result = 16 }
}
@@ -51,7 +46,7 @@ class BinaryLogicalOperation extends BinaryOperation, @bin_log_op_expr {
class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
override string getOperator() { result = "&&" }
override string getAPrimaryQlClass() { result = "LogicalAndExpr" }
override string getCanonicalQLClass() { result = "LogicalAndExpr" }
override int getPrecedence() { result = 5 }
@@ -72,7 +67,7 @@ class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr {
override string getOperator() { result = "||" }
override string getAPrimaryQlClass() { result = "LogicalOrExpr" }
override string getCanonicalQLClass() { result = "LogicalOrExpr" }
override int getPrecedence() { result = 4 }
@@ -94,7 +89,7 @@ class ConditionalExpr extends Operation, @conditionalexpr {
/** Gets the condition of this conditional expression. */
Expr getCondition() { expr_cond_guard(underlyingElement(this), unresolveElement(result)) }
override string getAPrimaryQlClass() { result = "ConditionalExpr" }
override string getCanonicalQLClass() { result = "ConditionalExpr" }
/** Gets the 'then' expression of this conditional expression. */
Expr getThen() {

View File

@@ -1,7 +1,3 @@
/**
* DEPRECATED: Objective-C is no longer supported.
*/
import semmle.code.cpp.exprs.Expr
import semmle.code.cpp.Class
import semmle.code.cpp.ObjectiveC

View File

@@ -1,47 +1,3 @@
/**
* Provides classes that describe the Intermediate Representation (IR) of the program.
*
* The IR is a representation of the semantics of the program, with very little dependence on the
* syntax that was used to write the program. For example, in C++, the statements `i += 1;`, `i++`,
* and `++i` all have the same semantic effect, but appear in the AST as three different types of
* `Expr` node. In the IR, all three statements are broken down into a sequence of fundamental
* operations similar to:
*
* ```
* r1(int*) = VariableAddress[i] // Compute the address of variable `i`
* r2(int) = Load &:r1, m0 // Load the value of `i`
* r3(int) = Constant[1] // An integer constant with the value `1`
* r4(int) = Add r2, r3 // Add `1` to the value of `i`
* r5(int) = Store &r1, r4 // Store the new value back into the variable `i`
* ```
*
* This allows IR-based analysis to focus on the fundamental operations, rather than having to be
* concerned with the various ways of expressing those operations in source code.
*
* The key classes in the IR are:
*
* - `IRFunction` - Contains the IR for an entire function definition, including all of that
* function's `Instruction`s, `IRBlock`s, and `IRVariables`.
* - `Instruction` - A single operation in the IR. An instruction specifies the operation to be
* performed, the operands that produce the inputs to that operation, and the type of the result
* of the operation. Control flows from an `Instruction` to one of a set of successor
* `Instruction`s.
* - `Operand` - An input value of an `Instruction`. All inputs of an `Instruction` are explicitly
* represented as `Operand`s, even if the input was implicit in the source code. An `Operand` has
* a link to the `Instruction` that consumes its value (its "use") and a link to the `Instruction`
* that produces its value (its "definition").
* - `IRVariable` - A variable accessed by the IR for a particular function. An `IRVariable` is
* created for each variable directly accessed by the function. In addition, `IRVariable`s are
* created to represent certain temporary storage locations that do not have explicitly declared
* variables in the source code, such as the return value of the function.
* - `IRBlock` - A "basic block" in the control flow graph of a function. An `IRBlock` contains a
* sequence of instructions such that control flow can only enter the block at the first
* instruction, and can only leave the block from the last instruction.
* - `IRType` - The type of a value accessed in the IR. Unlike the `Type` class in the AST, `IRType`
* is language-neutral. For example, in C++, `unsigned int`, `char32_t`, and `wchar_t` might all
* be represented as the `IRType` `uint4`, a four-byte unsigned integer.
*/
// Most queries should operate on the aliased SSA IR, so that's what we expose
// publicly as the "IR".
// publically as the "IR".
import implementation.aliased_ssa.IR

View File

@@ -1,5 +1 @@
/**
* Module used to configure the IR generation process.
*/
import implementation.IRConfiguration

View File

@@ -1,11 +1 @@
/**
* Outputs a representation of the IR as a control flow graph.
*
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
* dump.
*/
import implementation.aliased_ssa.PrintIR

View File

@@ -70,7 +70,7 @@ private DataFlow::Node getNodeForSource(Expr source) {
//
// This case goes together with the similar (but not identical) rule in
// `nodeIsBarrierIn`.
result = DataFlow::definitionByReferenceNodeFromArgument(source) and
result = DataFlow::definitionByReferenceNode(source) and
not argv(source.(VariableAccess).getTarget())
)
}
@@ -210,7 +210,7 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) {
or
// This case goes together with the similar (but not identical) rule in
// `getNodeForSource`.
node = DataFlow::definitionByReferenceNodeFromArgument(source)
node = DataFlow::definitionByReferenceNode(source)
)
}

View File

@@ -226,13 +226,28 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
}
/**
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
* Holds if the call context `ctx` reduces the set of viable dispatch
* targets of `ma` in `c`.
*/
predicate mayBenefitFromCallContext(CallInstruction call, Function f) { none() }
predicate reducedViableImplInCallContext(CallInstruction call, Function f, CallInstruction ctx) {
none()
}
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s for which the context makes a difference.
*/
Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() }
Function prunedViableImplInCallContext(CallInstruction call, CallInstruction ctx) { none() }
/**
* Holds if flow returning from `m` to `ma` might return further and if
* this path restricts the set of call sites that can be returned to.
*/
predicate reducedViableImplInReturn(Function f, CallInstruction call) { none() }
/**
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s and results for which the return flow from the
* result to `ma` restricts the possible context `ctx`.
*/
Function prunedViableImplInCallContextReverse(CallInstruction call, CallInstruction ctx) { none() }

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -19,7 +19,7 @@ import DataFlowImplSpecific::Public
* a subclass whose characteristic predicate is a unique singleton string.
* For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends DataFlow::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -37,7 +37,7 @@ import DataFlowImplSpecific::Public
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*
@@ -1051,17 +1051,6 @@ private predicate flowIntoCallNodeCand2(
}
private module LocalFlowBigStep {
/**
* A node where some checking is required, and hence the big-step relation
* is not allowed to step over.
*/
private class FlowCheckNode extends Node {
FlowCheckNode() {
this instanceof CastNode or
clearsContent(this, _)
}
}
/**
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
@@ -1076,7 +1065,7 @@ private module LocalFlowBigStep {
node instanceof OutNodeExt or
store(_, _, node, _) or
read(_, _, node) or
node instanceof FlowCheckNode
node instanceof CastNode
)
}
@@ -1094,7 +1083,7 @@ private module LocalFlowBigStep {
read(node, _, next)
)
or
node instanceof FlowCheckNode
node instanceof CastNode
or
config.isSink(node)
}
@@ -1124,11 +1113,11 @@ private module LocalFlowBigStep {
(
localFlowStepNodeCand1(node1, node2, config) and
preservesValue = true and
t = getNodeType(node1)
t = getErasedNodeTypeBound(node1)
or
additionalLocalFlowStepNodeCand2(node1, node2, config) and
preservesValue = false and
t = getNodeType(node2)
t = getErasedNodeTypeBound(node2)
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
@@ -1138,16 +1127,16 @@ private module LocalFlowBigStep {
exists(Node mid |
localFlowStepPlus(node1, mid, preservesValue, t, config, cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
nodeCand2(node2, unbind(config))
)
or
exists(Node mid |
localFlowStepPlus(node1, mid, _, _, config, cc) and
additionalLocalFlowStepNodeCand2(mid, node2, config) and
not mid instanceof FlowCheckNode and
not mid instanceof CastNode and
preservesValue = false and
t = getNodeType(node2) and
t = getErasedNodeTypeBound(node2) and
nodeCand2(node2, unbind(config))
)
)
@@ -1201,8 +1190,9 @@ private predicate flowCandFwd(
Configuration config
) {
flowCandFwd0(node, fromArg, argApf, apf, config) and
not apf.isClearedAt(node) and
if node instanceof CastingNode then compatibleTypes(getNodeType(node), apf.getType()) else any()
if node instanceof CastingNode
then compatibleTypes(getErasedNodeTypeBound(node), apf.getType())
else any()
}
pragma[nomagic]
@@ -1214,7 +1204,7 @@ private predicate flowCandFwd0(
config.isSource(node) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
or
exists(Node mid |
flowCandFwd(mid, fromArg, argApf, apf, config) and
@@ -1240,7 +1230,7 @@ private predicate flowCandFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argApf = TAccessPathFrontNone() and
apf = TFrontNil(getNodeType(node))
apf = TFrontNil(getErasedNodeTypeBound(node))
)
or
// store
@@ -1670,7 +1660,7 @@ private predicate flowFwd0(
config.isSource(node) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
or
flowCand(node, _, _, _, unbind(config)) and
@@ -1698,7 +1688,7 @@ private predicate flowFwd0(
additionalJumpStep(mid, node, config) and
fromArg = false and
argAp = TAccessPathNone() and
ap = TNil(getNodeType(node)) and
ap = TNil(getErasedNodeTypeBound(node)) and
apf = ap.(AccessPathNil).getFront()
)
)
@@ -2075,7 +2065,7 @@ private newtype TPathNode =
config.isSource(node) and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
@@ -2302,7 +2292,7 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, SummaryCt
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TNil(getNodeType(node))
ap = TNil(getErasedNodeTypeBound(node))
or
exists(TypedContent tc | pathStoreStep(mid, node, pop(tc, ap), tc, cc)) and
sc = mid.getSummaryCtx()
@@ -2644,7 +2634,7 @@ private module FlowExploration {
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
not fullBarrier(node, config) and
exists(config.explorationLimit())
or
@@ -2661,7 +2651,7 @@ private module FlowExploration {
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
then compatibleTypes(getErasedNodeTypeBound(node), ap.getType())
else any()
)
}
@@ -2774,7 +2764,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
)
or
@@ -2790,7 +2780,7 @@ private module FlowExploration {
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(getNodeType(node)) and
ap = TPartialNil(getErasedNodeTypeBound(node)) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
@@ -2804,7 +2794,7 @@ private module FlowExploration {
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
apConsFwd(ap, tc, ap0, config) and
compatibleTypes(ap.getType(), getNodeType(node))
compatibleTypes(ap.getType(), getErasedNodeTypeBound(node))
)
or
partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)

View File

@@ -22,7 +22,7 @@ private module Cached {
exists(int i |
viableParam(call, i, p) and
arg.argumentOf(call, i) and
compatibleTypes(getNodeType(arg), getNodeType(p))
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(p))
)
}
@@ -147,6 +147,54 @@ private module Cached {
}
}
private module LocalFlowBigStep {
private predicate localFlowEntry(Node n) {
Cand::cand(_, n) and
(
n instanceof ParameterNode or
n instanceof OutNode or
readStep(_, _, n) or
n instanceof CastNode
)
}
private predicate localFlowExit(Node n) {
Cand::cand(_, n) and
(
n instanceof ArgumentNode
or
n instanceof ReturnNode
or
readStep(n, _, _)
or
n instanceof CastNode
or
n =
any(PostUpdateNode pun | Cand::parameterValueFlowsToPreUpdateCand(_, pun))
.getPreUpdateNode()
)
}
pragma[nomagic]
private predicate localFlowStepPlus(Node node1, Node node2) {
localFlowEntry(node1) and
simpleLocalFlowStep(node1, node2) and
node1 != node2
or
exists(Node mid |
localFlowStepPlus(node1, mid) and
simpleLocalFlowStep(mid, node2) and
not mid instanceof CastNode
)
}
pragma[nomagic]
predicate localFlowBigStep(Node node1, Node node2) {
localFlowStepPlus(node1, node2) and
localFlowExit(node2)
}
}
/**
* The final flow-through calculation:
*
@@ -170,10 +218,10 @@ private module Cached {
then
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(p), getNodeType(node))
compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node))
or
// getter
compatibleTypes(read.getContentType(), getNodeType(node))
compatibleTypes(read.getContentType(), getErasedNodeTypeBound(node))
else any()
}
@@ -186,7 +234,7 @@ private module Cached {
// local flow
exists(Node mid |
parameterValueFlow(p, mid, read) and
simpleLocalFlowStep(mid, node)
LocalFlowBigStep::localFlowBigStep(mid, node)
)
or
// read
@@ -195,26 +243,19 @@ private module Cached {
readStepWithTypes(mid, read.getContainerType(), read.getContent(), node,
read.getContentType()) and
Cand::parameterValueFlowReturnCand(p, _, true) and
compatibleTypes(getNodeType(p), read.getContainerType())
compatibleTypes(getErasedNodeTypeBound(p), read.getContainerType())
)
or
parameterValueFlow0_0(TReadStepTypesNone(), p, node, read)
}
pragma[nomagic]
private predicate parameterValueFlow0_0(
ReadStepTypesOption mustBeNone, ParameterNode p, Node node, ReadStepTypesOption read
) {
// flow through: no prior read
exists(ArgumentNode arg |
parameterValueFlowArg(p, arg, mustBeNone) and
parameterValueFlowArg(p, arg, TReadStepTypesNone()) and
argumentValueFlowsThrough(arg, read, node)
)
or
// flow through: no read inside method
exists(ArgumentNode arg |
parameterValueFlowArg(p, arg, read) and
argumentValueFlowsThrough(arg, mustBeNone, node)
argumentValueFlowsThrough(arg, TReadStepTypesNone(), node)
)
}
@@ -251,11 +292,11 @@ private module Cached {
|
// normal flow through
read = TReadStepTypesNone() and
compatibleTypes(getNodeType(arg), getNodeType(out))
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out))
or
// getter
compatibleTypes(getNodeType(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getNodeType(out))
compatibleTypes(getErasedNodeTypeBound(arg), read.getContainerType()) and
compatibleTypes(read.getContentType(), getErasedNodeTypeBound(out))
)
}
@@ -289,67 +330,6 @@ private module Cached {
import Final
}
import FlowThrough
cached
private module DispatchWithCallContext {
/**
* Holds if the call context `ctx` reduces the set of viable run-time
* dispatch targets of call `call` in `c`.
*/
cached
predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) {
exists(int tgts, int ctxtgts |
mayBenefitFromCallContext(call, c) and
c = viableCallable(ctx) and
ctxtgts = count(viableImplInCallContext(call, ctx)) and
tgts = strictcount(viableCallable(call)) and
ctxtgts < tgts
)
}
/**
* Gets a viable run-time dispatch target for the call `call` in the
* context `ctx`. This is restricted to those calls for which a context
* makes a difference.
*/
cached
DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
reducedViableImplInCallContext(call, _, ctx)
}
/**
* Holds if flow returning from callable `c` to call `call` might return
* further and if this path restricts the set of call sites that can be
* returned to.
*/
cached
predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) {
exists(int tgts, int ctxtgts |
mayBenefitFromCallContext(call, _) and
c = viableCallable(call) and
ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContext(call, ctx)) and
tgts = strictcount(DataFlowCall ctx | viableCallable(ctx) = call.getEnclosingCallable()) and
ctxtgts < tgts
)
}
/**
* Gets a viable run-time dispatch target for the call `call` in the
* context `ctx`. This is restricted to those calls and results for which
* the return flow from the result to `call` restricts the possible context
* `ctx`.
*/
cached
DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) {
result = viableImplInCallContext(call, ctx) and
reducedViableImplInReturn(result, call)
}
}
import DispatchWithCallContext
/**
* Holds if `p` can flow to the pre-update node associated with post-update
* node `n`, in the same callable, using only value-preserving steps.
@@ -364,8 +344,8 @@ private module Cached {
) {
storeStep(node1, c, node2) and
readStep(_, c, _) and
contentType = getNodeType(node1) and
containerType = getNodeType(node2)
contentType = getErasedNodeTypeBound(node1) and
containerType = getErasedNodeTypeBound(node2)
or
exists(Node n1, Node n2 |
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
@@ -374,8 +354,8 @@ private module Cached {
argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1)
or
readStep(n2, c, n1) and
contentType = getNodeType(n1) and
containerType = getNodeType(n2)
contentType = getErasedNodeTypeBound(n1) and
containerType = getErasedNodeTypeBound(n2)
)
}
@@ -391,6 +371,8 @@ private module Cached {
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
}
import FlowThrough
/**
* Holds if the call context `call` either improves virtual dispatch in
* `callable` or if it allows us to prune unreachable nodes in `callable`.
@@ -466,8 +448,8 @@ private predicate readStepWithTypes(
Node n1, DataFlowType container, Content c, Node n2, DataFlowType content
) {
readStep(n1, c, n2) and
container = getNodeType(n1) and
content = getNodeType(n2)
container = getErasedNodeTypeBound(n1) and
content = getErasedNodeTypeBound(n2)
}
private newtype TReadStepTypesOption =
@@ -730,6 +712,9 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
result = viableCallable(call) and cc instanceof CallContextReturn
}
pragma[noinline]
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
predicate read = readStep/3;
/** An optional Boolean value. */
@@ -769,13 +754,6 @@ abstract class AccessPathFront extends TAccessPathFront {
abstract boolean toBoolNonEmpty();
predicate headUsesContent(TypedContent tc) { this = TFrontHead(tc) }
predicate isClearedAt(Node n) {
exists(TypedContent tc |
this.headUsesContent(tc) and
clearsContent(n, tc.getContent())
)
}
}
class AccessPathFrontNil extends AccessPathFront, TFrontNil {

View File

@@ -37,12 +37,21 @@ module Consistency {
)
}
query predicate uniqueType(Node n, string msg) {
query predicate uniqueTypeBound(Node n, string msg) {
exists(int c |
n instanceof RelevantNode and
c = count(getNodeType(n)) and
c = count(n.getTypeBound()) and
c != 1 and
msg = "Node should have one type but has " + c + "."
msg = "Node should have one type bound but has " + c + "."
)
}
query predicate uniqueTypeRepr(Node n, string msg) {
exists(int c |
n instanceof RelevantNode and
c = count(getErasedRepr(n.getTypeBound())) and
c != 1 and
msg = "Node should have one type representation but has " + c + "."
)
}
@@ -95,7 +104,7 @@ module Consistency {
msg = "Local flow step does not preserve enclosing callable."
}
private DataFlowType typeRepr() { result = getNodeType(_) }
private DataFlowType typeRepr() { result = getErasedRepr(any(Node n).getTypeBound()) }
query predicate compatibleTypesReflexive(DataFlowType t, string msg) {
t = typeRepr() and

View File

@@ -227,31 +227,28 @@ predicate readStep(Node node1, Content f, Node node2) {
}
/**
* Holds if values stored inside content `c` are cleared at node `n`.
* Gets a representative (boxed) type for `t` for the purpose of pruning
* possible flow. A single type is used for all numeric types to account for
* numeric conversions, and otherwise the erasure is used.
*/
predicate clearsContent(Node n, Content c) {
none() // stub implementation
Type getErasedRepr(Type t) {
suppressUnusedType(t) and
result instanceof VoidType // stub implementation
}
/** Gets the type of `n` used for type pruning. */
IRType getNodeType(Node n) {
suppressUnusedNode(n) and
result instanceof IRVoidType // stub implementation
}
/** Gets a string representation of a type returned by `getNodeType`. */
string ppReprType(IRType t) { none() } // stub implementation
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(Type t) { none() } // stub implementation
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(IRType t1, IRType t2) {
predicate compatibleTypes(Type t1, Type t2) {
any() // stub implementation
}
private predicate suppressUnusedNode(Node n) { any() }
private predicate suppressUnusedType(Type t) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
@@ -271,7 +268,7 @@ class DataFlowCallable = Declaration;
class DataFlowExpr = Expr;
class DataFlowType = IRType;
class DataFlowType = Type;
/** A function call relevant for data flow. */
class DataFlowCall extends CallInstruction {
@@ -303,4 +300,4 @@ predicate isImmutableOrUnobservable(Node n) {
}
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof OperandNode }
predicate nodeIsHidden(Node n) { none() }

View File

@@ -13,7 +13,6 @@ private import semmle.code.cpp.models.interfaces.DataFlow
private newtype TIRDataFlowNode =
TInstructionNode(Instruction i) or
TOperandNode(Operand op) or
TVariableNode(Variable var)
/**
@@ -33,23 +32,15 @@ class Node extends TIRDataFlowNode {
Function getFunction() { none() } // overridden in subclasses
/** Gets the type of this node. */
IRType getType() { none() } // overridden in subclasses
Type getType() { none() } // overridden in subclasses
/** Gets the instruction corresponding to this node, if any. */
Instruction asInstruction() { result = this.(InstructionNode).getInstruction() }
/** Gets the operands corresponding to this node, if any. */
Operand asOperand() { result = this.(OperandNode).getOperand() }
/**
* Gets the non-conversion expression corresponding to this node, if any.
* This predicate only has a result on nodes that represent the value of
* evaluating the expression. For data flowing _out of_ an expression, like
* when an argument is passed by reference, use `asDefiningArgument` instead
* of `asExpr`.
*
* If this node strictly (in the sense of `asConvertedExpr`) corresponds to
* a `Conversion`, then the result is the underlying non-`Conversion` base
* Gets the non-conversion expression corresponding to this node, if any. If
* this node strictly (in the sense of `asConvertedExpr`) corresponds to a
* `Conversion`, then the result is that `Conversion`'s non-`Conversion` base
* expression.
*/
Expr asExpr() { result = this.(ExprNode).getExpr() }
@@ -60,13 +51,7 @@ class Node extends TIRDataFlowNode {
*/
Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() }
/**
* Gets the argument that defines this `DefinitionByReferenceNode`, if any.
* This predicate should be used instead of `asExpr` when referring to the
* value of a reference argument _after_ the call has returned. For example,
* in `f(&x)`, this predicate will have `&x` as its result for the `Node`
* that represents the new value of `x`.
*/
/** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() }
/** Gets the positional parameter corresponding to this node, if any. */
@@ -74,7 +59,7 @@ class Node extends TIRDataFlowNode {
/**
* Gets the variable corresponding to this node, if any. This can be used for
* modeling flow in and out of global variables.
* modelling flow in and out of global variables.
*/
Variable asVariable() { result = this.(VariableNode).getVariable() }
@@ -99,7 +84,7 @@ class Node extends TIRDataFlowNode {
/**
* Gets an upper bound on the type of this node.
*/
IRType getTypeBound() { result = getType() }
Type getTypeBound() { result = getType() }
/** Gets the location of this element. */
Location getLocation() { none() } // overridden by subclasses
@@ -136,7 +121,7 @@ class InstructionNode extends Node, TInstructionNode {
override Function getFunction() { result = instr.getEnclosingFunction() }
override IRType getType() { result = instr.getResultIRType() }
override Type getType() { result = instr.getResultType() }
override Location getLocation() { result = instr.getLocation() }
@@ -147,28 +132,6 @@ class InstructionNode extends Node, TInstructionNode {
}
}
/**
* An operand, viewed as a node in a data flow graph.
*/
class OperandNode extends Node, TOperandNode {
Operand op;
OperandNode() { this = TOperandNode(op) }
/** Gets the operand corresponding to this node. */
Operand getOperand() { result = op }
override Declaration getEnclosingCallable() { result = this.getFunction() }
override Function getFunction() { result = op.getUse().getEnclosingFunction() }
override IRType getType() { result = op.getIRType() }
override Location getLocation() { result = op.getLocation() }
override string toString() { result = this.getOperand().toString() }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
@@ -328,7 +291,7 @@ abstract class PostUpdateNode extends InstructionNode {
* setY(&x); // a partial definition of the object `x`.
* ```
*/
abstract private class PartialDefinitionNode extends PostUpdateNode {
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
abstract Expr getDefinedExpr();
}
@@ -343,11 +306,11 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
)
}
// By using an operand as the result of this predicate we avoid the dataflow inconsistency errors
// caused by having multiple nodes sharing the same pre update node. This inconsistency error can cause
// a tuple explosion in the big step dataflow relation since it can make many nodes be the entry node
// into a big step.
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
// There might be multiple `ChiInstructions` that has a particular instruction as
// the total operand - so this definition gives consistency errors in
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
// this consistency failure has.
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
override Expr getDefinedExpr() {
result = field.getObjectAddress().getUnconvertedResultExpression()
@@ -389,7 +352,7 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
class DefinitionByReferenceNode extends InstructionNode {
override WriteSideEffectInstruction instr;
/** Gets the unconverted argument corresponding to this node. */
/** Gets the argument corresponding to this node. */
Expr getArgument() {
result =
instr
@@ -439,7 +402,7 @@ private class ArgumentIndirectionNode extends InstructionNode {
/**
* A `Node` corresponding to a variable in the program, as opposed to the
* value of that variable at some particular point. This can be used for
* modeling flow in and out of global variables.
* modelling flow in and out of global variables.
*/
class VariableNode extends Node, TVariableNode {
Variable v;
@@ -460,7 +423,7 @@ class VariableNode extends Node, TVariableNode {
result = v
}
override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) }
override Type getType() { result = v.getType() }
override Location getLocation() { result = v.getLocation() }
@@ -473,26 +436,20 @@ class VariableNode extends Node, TVariableNode {
InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr }
/**
* DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
*
* Gets the `Node` corresponding to a definition by reference of the variable
* that is passed as `argument` of a call.
*/
deprecated DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
/**
* Gets the `Node` corresponding to the value of evaluating `e` or any of its
* conversions. There is no result if `e` is a `Conversion`. For data flowing
* _out of_ an expression, like when an argument is passed by reference, use
* `definitionByReferenceNodeFromArgument` instead.
* Gets a `Node` corresponding to `e` or any of its conversions. There is no
* result if `e` is a `Conversion`.
*/
ExprNode exprNode(Expr e) { result.getExpr() = e }
/**
* Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may
* be a `Conversion`. For data flowing _out of_ an expression, like when an
* argument is passed by reference, use
* `definitionByReferenceNodeFromArgument` instead.
* Gets the `Node` corresponding to `e`, if any. Here, `e` may be a
* `Conversion`.
*/
ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
@@ -501,14 +458,6 @@ ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e }
*/
ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p }
/**
* Gets the `Node` corresponding to a definition by reference of the variable
* that is passed as unconverted `argument` of a call.
*/
DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) {
result.getArgument() = argument
}
/** Gets the `VariableNode` corresponding to the variable `v`. */
VariableNode variableNode(Variable v) { result.getVariable() = v }
@@ -533,11 +482,7 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Instruction -> Instruction flow
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
or
// Operand -> Instruction flow
simpleOperandLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
}
pragma[noinline]
@@ -549,16 +494,6 @@ private predicate getFieldSizeOfClass(Class c, Type type, int size) {
)
}
private predicate simpleOperandLocalFlowStep(Operand opFrom, Instruction iTo) {
// Certain dataflow steps (for instance `PostUpdateNode.getPreUpdateNode()`) generates flow to
// operands, so we include dataflow from those operands to the "result" of the instruction (i.e., to
// the instruction itself).
exists(PostUpdateNode post |
opFrom = post.getPreUpdateNode().asOperand() and
iTo.getAnOperand() = opFrom
)
}
cached
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
iTo.(CopyInstruction).getSourceValue() = iFrom
@@ -724,20 +659,13 @@ predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)
*/
class BarrierGuard extends IRGuardCondition {
/** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */
predicate checksInstr(Instruction instr, boolean b) { none() }
/** Override this predicate to hold if this guard validates `expr` upon evaluating to `b`. */
predicate checks(Expr e, boolean b) { none() }
abstract predicate checks(Instruction instr, boolean b);
/** Gets a node guarded by this guard. */
final Node getAGuardedNode() {
exists(ValueNumber value, boolean edge |
(
this.checksInstr(value.getAnInstruction(), edge)
or
this.checks(value.getAnInstruction().getConvertedResultExpression(), edge)
) and
result.asInstruction() = value.getAnInstruction() and
this.checks(value.getAnInstruction(), edge) and
this.controls(result.asInstruction().getBlock(), edge)
)
}

View File

@@ -26,7 +26,7 @@ private import TaintTrackingParameter::Private
* To create a configuration, extend this class with a subclass whose
* characteristic predicate is a unique singleton string. For example, write
*
* ```ql
* ```
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
* // Override `isSource` and `isSink`.
@@ -41,7 +41,7 @@ private import TaintTrackingParameter::Private
* Then, to query whether there is flow between some `source` and `sink`,
* write
*
* ```ql
* ```
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
* ```
*

Some files were not shown because too many files have changed in this diff Show More