mirror of
https://github.com/github/codeql.git
synced 2025-12-22 03:36:30 +01:00
Merge branch 'main' into rdmarsh2/dataflow-global-vars
This commit is contained in:
@@ -1,3 +1,19 @@
|
||||
## 0.3.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
|
||||
|
||||
## 0.2.3
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
|
||||
4
cpp/ql/lib/change-notes/2022-06-24-unique-variable.md
Normal file
4
cpp/ql/lib/change-notes/2022-06-24-unique-variable.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Under certain circumstances a variable declaration that is not also a definition could be associated with a `Variable` that did not have the definition as a `VariableDeclarationEntry`. This is now fixed, and a unique `Variable` will exist that has both the declaration and the definition as a `VariableDeclarationEntry`.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added subclasses of `BuiltInOperations` for `__builtin_bit_cast`, `__builtin_shuffle`, `__has_unique_object_representations`, `__is_aggregate`, and `__is_assignable`.
|
||||
9
cpp/ql/lib/change-notes/released/0.3.0.md
Normal file
9
cpp/ql/lib/change-notes/released/0.3.0.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 0.3.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* `UserType.getADeclarationEntry()` now yields all forward declarations when the user type is a `class`, `struct`, or `union`.
|
||||
5
cpp/ql/lib/change-notes/released/0.3.1.md
Normal file
5
cpp/ql/lib/change-notes/released/0.3.1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.3.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* `AnalysedExpr::isNullCheck` and `AnalysedExpr::isValidCheck` have been updated to handle variable accesses on the left-hand side of the C++ logical "and", and variable declarations in conditions.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.2.3
|
||||
lastReleaseVersion: 0.3.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.3.0-dev
|
||||
version: 0.3.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import semmle.code.cpp.Location
|
||||
private import semmle.code.cpp.Enclosing
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
private import semmle.code.cpp.internal.ResolveGlobalVariable
|
||||
|
||||
/**
|
||||
* Get the `Element` that represents this `@element`.
|
||||
@@ -28,9 +29,12 @@ Element mkElement(@element e) { unresolveElement(result) = e }
|
||||
pragma[inline]
|
||||
@element unresolveElement(Element e) {
|
||||
not result instanceof @usertype and
|
||||
not result instanceof @variable and
|
||||
result = e
|
||||
or
|
||||
e = resolveClass(result)
|
||||
or
|
||||
e = resolveGlobalVariable(result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import semmle.code.cpp.Element
|
||||
import semmle.code.cpp.exprs.Access
|
||||
import semmle.code.cpp.Initializer
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
private import semmle.code.cpp.internal.ResolveGlobalVariable
|
||||
|
||||
/**
|
||||
* A C/C++ variable. For example, in the following code there are four
|
||||
@@ -32,6 +33,8 @@ private import semmle.code.cpp.internal.ResolveClass
|
||||
* can have multiple declarations.
|
||||
*/
|
||||
class Variable extends Declaration, @variable {
|
||||
Variable() { isVariable(underlyingElement(this)) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Variable" }
|
||||
|
||||
/** Gets the initializer of this variable, if any. */
|
||||
|
||||
@@ -46,7 +46,7 @@ predicate nullCheckExpr(Expr checkExpr, Variable var) {
|
||||
or
|
||||
exists(LogicalAndExpr op, AnalysedExpr child |
|
||||
expr = op and
|
||||
op.getRightOperand() = child and
|
||||
op.getAnOperand() = child and
|
||||
nullCheckExpr(child, v)
|
||||
)
|
||||
or
|
||||
@@ -99,7 +99,7 @@ predicate validCheckExpr(Expr checkExpr, Variable var) {
|
||||
or
|
||||
exists(LogicalAndExpr op, AnalysedExpr child |
|
||||
expr = op and
|
||||
op.getRightOperand() = child and
|
||||
op.getAnOperand() = child and
|
||||
validCheckExpr(child, v)
|
||||
)
|
||||
or
|
||||
@@ -169,7 +169,10 @@ class AnalysedExpr extends Expr {
|
||||
*/
|
||||
predicate isDef(LocalScopeVariable v) {
|
||||
this.inCondition() and
|
||||
this.(Assignment).getLValue() = v.getAnAccess()
|
||||
(
|
||||
this.(Assignment).getLValue() = v.getAnAccess() or
|
||||
this.(ConditionDeclExpr).getVariableAccess() = v.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides classes for modeling built-in operations. Built-in operations are
|
||||
* Provides classes for modeling built-in operations. Built-in operations are
|
||||
* typically compiler specific and are used by libraries and generated code.
|
||||
*/
|
||||
|
||||
@@ -120,8 +120,8 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
|
||||
|
||||
/**
|
||||
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
|
||||
* of `offsetof`). The operation retains its semantics even in the presence
|
||||
* of an overloaded `operator &`). This is a GNU/Clang extension.
|
||||
* of `offsetof`). The operation retains its semantics even in the presence
|
||||
* of an overloaded `operator &`). This is a gcc/clang extension.
|
||||
* ```
|
||||
* struct S {
|
||||
* int a, b;
|
||||
@@ -137,8 +137,8 @@ class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
|
||||
|
||||
/**
|
||||
* A C/C++ `__INTADDR__` built-in operation (used by some implementations
|
||||
* of `offsetof`). The operation retains its semantics even in the presence
|
||||
* of an overloaded `operator &`). This is an EDG extension.
|
||||
* of `offsetof`). The operation retains its semantics even in the presence
|
||||
* of an overloaded `operator &`). This is an EDG extension.
|
||||
* ```
|
||||
* struct S {
|
||||
* int a, b;
|
||||
@@ -173,7 +173,7 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
|
||||
*
|
||||
* Returns `true` if the type has a copy constructor.
|
||||
* ```
|
||||
* std::integral_constant< bool, __has_copy(_Tp)> hc;
|
||||
* std::integral_constant<bool, __has_copy(_Tp)> hc;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
|
||||
@@ -189,7 +189,7 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
|
||||
* Returns `true` if a copy assignment operator has an empty exception
|
||||
* specification.
|
||||
* ```
|
||||
* std::integral_constant< bool, __has_nothrow_assign(_Tp)> hnta;
|
||||
* std::integral_constant<bool, __has_nothrow_assign(_Tp)> hnta;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
|
||||
@@ -220,7 +220,7 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
|
||||
*
|
||||
* Returns `true` if the copy constructor has an empty exception specification.
|
||||
* ```
|
||||
* std::integral_constant< bool, __has_nothrow_copy(MyType) >;
|
||||
* std::integral_constant<bool, __has_nothrow_copy(MyType) >;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
|
||||
@@ -266,7 +266,7 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
|
||||
*
|
||||
* Returns true if the type has a trivial copy constructor.
|
||||
* ```
|
||||
* std::integral_constant< bool, __has_trivial_copy(MyType) > htc;
|
||||
* std::integral_constant<bool, __has_trivial_copy(MyType)> htc;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
|
||||
@@ -468,7 +468,7 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
|
||||
* ```
|
||||
* template<typename _Tp1, typename _Tp2>
|
||||
* struct types_compatible
|
||||
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2) >
|
||||
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
@@ -479,8 +479,7 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
|
||||
/**
|
||||
* A clang `__builtin_shufflevector` expression.
|
||||
*
|
||||
* It outputs a permutation of elements from one or two input vectors.
|
||||
* Please see
|
||||
* It outputs a permutation of elements from one or two input vectors. See
|
||||
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
|
||||
* for more information.
|
||||
* ```
|
||||
@@ -494,11 +493,29 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffleVector" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A gcc `__builtin_shuffle` expression.
|
||||
*
|
||||
* It outputs a permutation of elements from one or two input vectors.
|
||||
* See https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
|
||||
* for more information.
|
||||
* ```
|
||||
* // Concatenate every other element of 4-element vectors V1 and V2.
|
||||
* M = {0, 2, 4, 6};
|
||||
* V3 = __builtin_shuffle(V1, V2, M);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationBuiltInShuffle extends BuiltInOperation, @builtinshuffle {
|
||||
override string toString() { result = "__builtin_shuffle" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationBuiltInShuffle" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A clang `__builtin_convertvector` expression.
|
||||
*
|
||||
* Allows for conversion of vectors of equal element count and compatible
|
||||
* element types. Please see
|
||||
* element types. See
|
||||
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
|
||||
* for more information.
|
||||
* ```
|
||||
@@ -547,7 +564,7 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
|
||||
* ```
|
||||
* template<typename T, typename... Args>
|
||||
* struct is_trivially_constructible
|
||||
* : public integral_constant<bool, __is_trivially_constructible(T, Args...) >
|
||||
* : public integral_constant<bool, __is_trivially_constructible(T, Args...)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
@@ -612,13 +629,10 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
|
||||
* The `__is_trivially_assignable` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the assignment operator `C::operator =(const C& c)` is
|
||||
* trivial.
|
||||
* Returns `true` if the assignment operator `C::operator =(const D& d)` is
|
||||
* trivial (i.e., it will not call any operation that is non-trivial).
|
||||
* ```
|
||||
* template<typename T>
|
||||
* struct is_trivially_assignable
|
||||
* : public integral_constant<bool, __is_trivially_assignable(T) >
|
||||
* { };
|
||||
* bool v = __is_trivially_assignable(MyType1, MyType2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
|
||||
@@ -631,10 +645,10 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
|
||||
* The `__is_nothrow_assignable` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns true if there exists a `C::operator =(const C& c) nothrow`
|
||||
* Returns true if there exists a `C::operator =(const D& d) nothrow`
|
||||
* assignment operator (i.e, with an empty exception specification).
|
||||
* ```
|
||||
* bool v = __is_nothrow_assignable(MyType);
|
||||
* bool v = __is_nothrow_assignable(MyType1, MyType2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
|
||||
@@ -643,15 +657,30 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsNothrowAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_assignable` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns true if there exists a `C::operator =(const D& d)` assignment
|
||||
* operator.
|
||||
* ```
|
||||
* bool v = __is_assignable(MyType1, MyType2);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsAssignable extends BuiltInOperation, @isassignable {
|
||||
override string toString() { result = "__is_assignable" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAssignable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_standard_layout` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
|
||||
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member
|
||||
* variable or (3) multiple occurrences of base `class` objects, among other
|
||||
* restrictions. Please see
|
||||
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
|
||||
* `union` without (1) virtual functions or base classes, (2) reference member
|
||||
* variable, or (3) multiple occurrences of base `class` objects, among other
|
||||
* restrictions. See https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
|
||||
* for more information.
|
||||
* ```
|
||||
* bool v = __is_standard_layout(MyType);
|
||||
@@ -668,7 +697,7 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if instances of this type can be copied by trivial
|
||||
* means. The copying is done in a manner similar to the `memcpy`
|
||||
* means. The copying is done in a manner similar to the `memcpy`
|
||||
* function.
|
||||
*/
|
||||
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
|
||||
@@ -682,13 +711,13 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
|
||||
* the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the type is a scalar type, a reference type or an array of
|
||||
* literal types, among others. Please see
|
||||
* literal types, among others. See
|
||||
* https://en.cppreference.com/w/cpp/named_req/LiteralType
|
||||
* for more information.
|
||||
*
|
||||
* ```
|
||||
* template <typename _Tp>
|
||||
* std::integral_constant< bool, __is_literal_type(_Tp)> ilt;
|
||||
* std::integral_constant<bool, __is_literal_type(_Tp)> ilt;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
|
||||
@@ -705,7 +734,7 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
|
||||
* compiler, with semantics of the `memcpy` operation.
|
||||
* ```
|
||||
* template <typename _Tp>
|
||||
* std::integral_constant< bool, __has_trivial_move_constructor(_Tp)> htmc;
|
||||
* std::integral_constant<bool, __has_trivial_move_constructor(_Tp)> htmc;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
|
||||
@@ -723,7 +752,7 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
|
||||
* ```
|
||||
* template<typename T>
|
||||
* struct has_trivial_move_assign
|
||||
* : public integral_constant<bool, __has_trivial_move_assign(T) >
|
||||
* : public integral_constant<bool, __has_trivial_move_assign(T)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
@@ -758,7 +787,7 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
|
||||
* ```
|
||||
* template<typename T, typename... Args>
|
||||
* struct is_constructible
|
||||
* : public integral_constant<bool, __is_constructible(T, Args...) >
|
||||
* : public integral_constant<bool, __is_constructible(T, Args...)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
@@ -785,7 +814,7 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
|
||||
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called
|
||||
* from either the regular destructor or the garbage collector.
|
||||
@@ -800,10 +829,10 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_delegate` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_delegate` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the function has been declared as a `delegate`, used in
|
||||
* message forwarding. Please see
|
||||
* message forwarding. See
|
||||
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
|
||||
* for more information.
|
||||
*/
|
||||
@@ -814,9 +843,9 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the type has been declared as an `interface`. Please see
|
||||
* Returns `true` if the type has been declared as an `interface`. See
|
||||
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
|
||||
* for more information.
|
||||
*/
|
||||
@@ -827,9 +856,9 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the object passed in is a _platform array_. Please see
|
||||
* Returns `true` if the object passed in is a _platform array_. See
|
||||
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
|
||||
* for more information.
|
||||
* ```
|
||||
@@ -844,9 +873,9 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if the type is a _reference class_. Please see
|
||||
* Returns `true` if the type is a _reference class_. See
|
||||
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
||||
* for more information.
|
||||
* ```
|
||||
@@ -861,10 +890,10 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_sealed` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_sealed` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if a given class or virtual function is marked as `sealed`,
|
||||
* meaning that it cannot be extended or overridden. The `sealed` keyword
|
||||
* meaning that it cannot be extended or overridden. The `sealed` keyword
|
||||
* is similar to the C++11 `final` keyword.
|
||||
* ```
|
||||
* ref class X sealed {
|
||||
@@ -879,7 +908,7 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if passed a value type that contains no references to the
|
||||
* garbage-collected heap.
|
||||
@@ -898,9 +927,9 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__is_value_class` built-in operation. This is a Microsoft extension.
|
||||
* The `__is_value_class` built-in operation. This is a Microsoft extension.
|
||||
*
|
||||
* Returns `true` if passed a value type. Please see
|
||||
* Returns `true` if passed a value type. See
|
||||
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
|
||||
* For more information.
|
||||
* ```
|
||||
@@ -922,7 +951,7 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
|
||||
* ```
|
||||
* template<typename T>
|
||||
* struct is_final
|
||||
* : public integral_constant<bool, __is_final(T) >
|
||||
* : public integral_constant<bool, __is_final(T)>
|
||||
* { };
|
||||
* ```
|
||||
*/
|
||||
@@ -933,7 +962,7 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension.
|
||||
* The `__builtin_choose_expr` expression. This is a gcc/clang extension.
|
||||
*
|
||||
* The expression functions similarly to the ternary `?:` operator, except
|
||||
* that it is evaluated at compile-time.
|
||||
@@ -978,3 +1007,50 @@ class BuiltInComplexOperation extends BuiltInOperation, @builtincomplex {
|
||||
/** Gets the operand corresponding to the imaginary part of the complex number. */
|
||||
Expr getImaginaryOperand() { this.hasChild(result, 1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_aggregate` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the type has is an aggregate type.
|
||||
* ```
|
||||
* std::integral_constant<bool, __is_aggregate(_Tp)> ia;
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate {
|
||||
override string toString() { result = "__is_aggregate" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsAggregate" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__has_unique_object_representations` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if the type is trivially copyable and if the object representation
|
||||
* is unique for two objects with the same value.
|
||||
* ```
|
||||
* bool v = __has_unique_object_representations(MyType);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation,
|
||||
@hasuniqueobjectrepresentations {
|
||||
override string toString() { result = "__has_unique_object_representations" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ `__builtin_bit_cast` built-in operation (used by some implementations
|
||||
* of `std::bit_cast`).
|
||||
*
|
||||
* Performs a bit cast from a value to a type.
|
||||
* ```
|
||||
* __builtin_bit_cast(Type, value);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInBitCast extends BuiltInOperation, @builtinbitcast {
|
||||
override string toString() { result = "__builtin_bit_cast" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInBitCast" }
|
||||
}
|
||||
|
||||
@@ -255,8 +255,10 @@ class FunctionCall extends Call, @funbindexpr {
|
||||
/**
|
||||
* Gets the function called by this call.
|
||||
*
|
||||
* In the case of virtual function calls, the result is the most-specific function in the override tree (as
|
||||
* determined by the compiler) such that the target at runtime will be one of `result.getAnOverridingFunction*()`.
|
||||
* In the case of virtual function calls, the result is the most-specific function in the override tree
|
||||
* such that the target at runtime will be one of `result.getAnOverridingFunction*()`. The most-specific
|
||||
* function is determined by the compiler based on the compile time type of the object the function is a
|
||||
* member of.
|
||||
*/
|
||||
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
|
||||
@@ -596,9 +596,12 @@ class ParenthesisExpr extends Conversion, @parexpr {
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ expression that has not been resolved.
|
||||
* A C/C++ expression that could not be resolved, or that can no longer be
|
||||
* represented due to a database upgrade or downgrade.
|
||||
*
|
||||
* It is assigned `ErroneousType` as its type.
|
||||
* If the expression could not be resolved, it has type `ErroneousType`. In the
|
||||
* case of a database upgrade or downgrade, the original type from before the
|
||||
* upgrade or downgrade is kept if that type can be represented.
|
||||
*/
|
||||
class ErrorExpr extends Expr, @errorexpr {
|
||||
override string toString() { result = "<error expr>" }
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
private predicate hasDefinition(@globalvariable g) {
|
||||
exists(@var_decl vd | var_decls(vd, g, _, _, _) | var_def(vd))
|
||||
}
|
||||
|
||||
private predicate onlyOneCompleteGlobalVariableExistsWithMangledName(@mangledname name) {
|
||||
strictcount(@globalvariable g | hasDefinition(g) and mangled_name(g, name)) = 1
|
||||
}
|
||||
|
||||
/** Holds if `g` is a unique global variable with a definition named `name`. */
|
||||
private predicate isGlobalWithMangledNameAndWithDefinition(@mangledname name, @globalvariable g) {
|
||||
hasDefinition(g) and
|
||||
mangled_name(g, name) and
|
||||
onlyOneCompleteGlobalVariableExistsWithMangledName(name)
|
||||
}
|
||||
|
||||
/** Holds if `g` is a global variable without a definition named `name`. */
|
||||
private predicate isGlobalWithMangledNameAndWithoutDefinition(@mangledname name, @globalvariable g) {
|
||||
not hasDefinition(g) and
|
||||
mangled_name(g, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `incomplete` is a global variable without a definition, and there exists
|
||||
* a unique global variable `complete` with the same name that does have a definition.
|
||||
*/
|
||||
private predicate hasTwinWithDefinition(@globalvariable incomplete, @globalvariable complete) {
|
||||
exists(@mangledname name |
|
||||
not variable_instantiation(incomplete, complete) and
|
||||
isGlobalWithMangledNameAndWithoutDefinition(name, incomplete) and
|
||||
isGlobalWithMangledNameAndWithDefinition(name, complete)
|
||||
)
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* If `v` is a global variable without a definition, and there exists a unique
|
||||
* global variable with the same name that does have a definition, then the
|
||||
* result is that unique global variable. Otherwise, the result is `v`.
|
||||
*/
|
||||
cached
|
||||
@variable resolveGlobalVariable(@variable v) {
|
||||
hasTwinWithDefinition(v, result)
|
||||
or
|
||||
not hasTwinWithDefinition(v, _) and
|
||||
result = v
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isVariable(@variable v) {
|
||||
not v instanceof @globalvariable
|
||||
or
|
||||
v = resolveGlobalVariable(_)
|
||||
}
|
||||
}
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
@@ -447,7 +447,7 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
@@ -466,7 +466,7 @@ private predicate additionalLocalStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -481,7 +481,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
@@ -494,7 +494,7 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
@@ -507,7 +507,7 @@ private predicate additionalJumpStateStep(
|
||||
exists(Node n1, Node n2 |
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, s1, n2, s2) and
|
||||
config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not stateBarrier(node1, s1, config) and
|
||||
@@ -518,7 +518,7 @@ private predicate additionalJumpStateStep(
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) {
|
||||
readSet(node1.asNode(), c, node2.asNode()) and
|
||||
readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
@@ -562,7 +562,8 @@ pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -1650,6 +1650,11 @@ case @expr.kind of
|
||||
| 327 = @co_await
|
||||
| 328 = @co_yield
|
||||
| 329 = @temp_init
|
||||
| 330 = @isassignable
|
||||
| 331 = @isaggregate
|
||||
| 332 = @hasuniqueobjectrepresentations
|
||||
| 333 = @builtinbitcast
|
||||
| 334 = @builtinshuffle
|
||||
;
|
||||
|
||||
@var_args_expr = @vastartexpr
|
||||
@@ -1711,6 +1716,11 @@ case @expr.kind of
|
||||
| @isfinalexpr
|
||||
| @builtinchooseexpr
|
||||
| @builtincomplex
|
||||
| @isassignable
|
||||
| @isaggregate
|
||||
| @hasuniqueobjectrepresentations
|
||||
| @builtinbitcast
|
||||
| @builtinshuffle
|
||||
;
|
||||
|
||||
new_allocated_type(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add new builtin operations
|
||||
compatibility: backwards
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.3.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.
|
||||
|
||||
## 0.2.0
|
||||
|
||||
## 0.1.4
|
||||
|
||||
## 0.1.3
|
||||
|
||||
@@ -44,7 +44,7 @@ predicate whiteListWrapped(FunctionCall fc) {
|
||||
|
||||
from FunctionCall c, FloatingPointType t1, IntegralType t2
|
||||
where
|
||||
t1 = c.getTarget().getType().getUnderlyingType() and
|
||||
pragma[only_bind_into](t1) = c.getTarget().getType().getUnderlyingType() and
|
||||
t2 = c.getActualType() and
|
||||
c.hasImplicitConversion() and
|
||||
not whiteListWrapped(c)
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
* @precision medium
|
||||
* @tags security
|
||||
* external/cwe/cwe-480
|
||||
* external/microsoft/c6317
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/string-copy-return-value-as-boolean
|
||||
* @tags external/microsoft/C6324
|
||||
* correctness
|
||||
* @tags correctness
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
* @id cpp/inconsistent-loop-direction
|
||||
* @tags correctness
|
||||
* external/cwe/cwe-835
|
||||
* external/microsoft/6293
|
||||
* @msrc.severity important
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.MustFlow
|
||||
import PathGraph
|
||||
|
||||
/** Holds if `f` has a name that we intrepret as evidence of intentionally returning the value of the stack pointer. */
|
||||
/** Holds if `f` has a name that we interpret as evidence of intentionally returning the value of the stack pointer. */
|
||||
predicate intentionallyReturnsStackPointer(Function f) {
|
||||
f.getName().toLowerCase().matches(["%stack%", "%sp%"])
|
||||
}
|
||||
@@ -74,13 +74,12 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
|
||||
from
|
||||
MustFlowPathNode source, MustFlowPathNode sink, VariableAddressInstruction var,
|
||||
ReturnStackAllocatedMemoryConfig conf, Function f
|
||||
ReturnStackAllocatedMemoryConfig conf
|
||||
where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
conf.hasFlowPath(pragma[only_bind_into](source), pragma[only_bind_into](sink)) and
|
||||
source.getNode().asInstruction() = var and
|
||||
// Only raise an alert if we're returning from the _same_ callable as the on that
|
||||
// declared the stack variable.
|
||||
var.getEnclosingFunction() = pragma[only_bind_into](f) and
|
||||
sink.getNode().getEnclosingCallable() = pragma[only_bind_into](f)
|
||||
var.getEnclosingFunction() = sink.getNode().getEnclosingCallable()
|
||||
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAst(),
|
||||
var.getAst().toString()
|
||||
|
||||
@@ -133,7 +133,9 @@ TGlobalAddress globalAddress(Instruction instr) {
|
||||
)
|
||||
or
|
||||
exists(FieldAddressInstruction fai | instr = fai |
|
||||
result = TFieldAddress(globalAddress(fai.getObjectAddress()), fai.getField())
|
||||
result =
|
||||
TFieldAddress(globalAddress(pragma[only_bind_into](fai.getObjectAddress())),
|
||||
pragma[only_bind_out](fai.getField()))
|
||||
)
|
||||
or
|
||||
result = globalAddress(instr.(PointerOffsetInstruction).getLeft())
|
||||
|
||||
@@ -15,6 +15,7 @@ class VariableAccessInInitializer extends VariableAccess {
|
||||
Variable var;
|
||||
Initializer init;
|
||||
|
||||
pragma[nomagic]
|
||||
VariableAccessInInitializer() {
|
||||
init.getDeclaration() = var and
|
||||
init.getExpr().getAChild*() = this
|
||||
|
||||
@@ -77,7 +77,7 @@ class ExecState extends DataFlow::FlowState {
|
||||
ExecState() {
|
||||
this =
|
||||
"ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and
|
||||
interestingConcatenation(fst, snd)
|
||||
interestingConcatenation(pragma[only_bind_into](fst), pragma[only_bind_into](snd))
|
||||
}
|
||||
|
||||
DataFlow::Node getFstNode() { result = fst }
|
||||
|
||||
@@ -8,11 +8,6 @@
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-253
|
||||
* external/microsoft/C6214
|
||||
* external/microsoft/C6215
|
||||
* external/microsoft/C6216
|
||||
* external/microsoft/C6217
|
||||
* external/microsoft/C6230
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
* @msrc.severity important
|
||||
* @tags security
|
||||
* external/cwe/cwe-428
|
||||
* external/microsoft/C6277
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-704
|
||||
* external/microsoft/c/c6276
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-732
|
||||
* external/microsoft/C6248
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
1
cpp/ql/src/change-notes/released/0.2.0.md
Normal file
1
cpp/ql/src/change-notes/released/0.2.0.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.2.0
|
||||
5
cpp/ql/src/change-notes/released/0.3.0.md
Normal file
5
cpp/ql/src/change-notes/released/0.3.0.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.3.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* Contextual queries and the query libraries they depend on have been moved to the `codeql/cpp-all` package.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.4
|
||||
lastReleaseVersion: 0.3.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.2.0-dev
|
||||
version: 0.3.1-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
// semmle-extractor-options: --clang
|
||||
struct mystruct {
|
||||
int f1;
|
||||
int f2;
|
||||
@@ -13,3 +13,6 @@ void f(void) {
|
||||
int i2 = edg_offsetof(struct mystruct,f2);
|
||||
}
|
||||
|
||||
void g(void) {
|
||||
double f = __builtin_bit_cast(double,42l);
|
||||
}
|
||||
|
||||
@@ -13,3 +13,6 @@
|
||||
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
|
||||
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
|
||||
| edg.c:13:43:13:44 | f2 | 0 | 0 |
|
||||
| edg.c:17:16:17:45 | __builtin_bit_cast | 1 | 1 |
|
||||
| edg.c:17:16:17:45 | double | 0 | 0 |
|
||||
| edg.c:17:42:17:44 | 42 | 1 | 1 |
|
||||
|
||||
@@ -296,3 +296,20 @@
|
||||
| ms.cpp:255:24:255:43 | a_struct | | <none> |
|
||||
| ms.cpp:256:24:256:49 | __is_final | a_final_struct | 1 |
|
||||
| ms.cpp:256:24:256:49 | a_final_struct | | <none> |
|
||||
| ms.cpp:258:29:258:62 | __is_assignable | a_struct,a_struct | 1 |
|
||||
| ms.cpp:258:29:258:62 | a_struct | | <none> |
|
||||
| ms.cpp:258:29:258:62 | a_struct | | <none> |
|
||||
| ms.cpp:259:29:259:59 | __is_assignable | a_struct,empty | 0 |
|
||||
| ms.cpp:259:29:259:59 | a_struct | | <none> |
|
||||
| ms.cpp:259:29:259:59 | empty | | <none> |
|
||||
| ms.cpp:260:29:260:57 | __is_assignable | a_struct,int | 0 |
|
||||
| ms.cpp:260:29:260:57 | a_struct | | <none> |
|
||||
| ms.cpp:260:29:260:57 | int | | <none> |
|
||||
| ms.cpp:262:28:262:51 | __is_aggregate | a_struct | 1 |
|
||||
| ms.cpp:262:28:262:51 | a_struct | | <none> |
|
||||
| ms.cpp:263:28:263:46 | __is_aggregate | int | 0 |
|
||||
| ms.cpp:263:28:263:46 | int | | <none> |
|
||||
| ms.cpp:265:49:265:88 | __has_unique_object_representations | int | 1 |
|
||||
| ms.cpp:265:49:265:88 | int | | <none> |
|
||||
| ms.cpp:266:49:266:90 | __has_unique_object_representations | float | 0 |
|
||||
| ms.cpp:266:49:266:90 | float | | <none> |
|
||||
|
||||
@@ -254,5 +254,14 @@ void f(void) {
|
||||
|
||||
bool b_is_final1 = __is_final(a_struct);
|
||||
bool b_is_final2 = __is_final(a_final_struct);
|
||||
}
|
||||
|
||||
bool b_is_assignable1 = __is_assignable(a_struct,a_struct);
|
||||
bool b_is_assignable2 = __is_assignable(a_struct,empty);
|
||||
bool b_is_assignable3 = __is_assignable(a_struct,int);
|
||||
|
||||
bool b_is_aggregate1 = __is_aggregate(a_struct);
|
||||
bool b_is_aggregate2 = __is_aggregate(int);
|
||||
|
||||
bool b_has_unique_object_representations1 = __has_unique_object_representations(int);
|
||||
bool b_has_unique_object_representations2 = __has_unique_object_representations(float);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
| test.cpp:9:9:9:9 | v | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:10:9:10:10 | ! ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:11:9:11:14 | ... == ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:12:9:12:17 | ... == ... | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:13:9:13:14 | ... != ... | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:14:9:14:17 | ... != ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:15:8:15:23 | call to __builtin_expect | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:16:8:16:23 | call to __builtin_expect | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:17:9:17:17 | ... && ... | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:18:9:18:17 | ... && ... | test.cpp:5:13:5:13 | v | is not null | is valid |
|
||||
| test.cpp:19:9:19:18 | ... && ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:20:9:20:18 | ... && ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:21:9:21:14 | ... = ... | test.cpp:5:13:5:13 | v | is null | is not valid |
|
||||
| test.cpp:21:9:21:14 | ... = ... | test.cpp:7:10:7:10 | b | is not null | is valid |
|
||||
| test.cpp:22:9:22:14 | ... = ... | test.cpp:5:13:5:13 | v | is not null | is not valid |
|
||||
| test.cpp:22:9:22:14 | ... = ... | test.cpp:7:13:7:13 | c | is not null | is not valid |
|
||||
| test.cpp:22:17:22:17 | c | test.cpp:7:13:7:13 | c | is not null | is valid |
|
||||
| test.cpp:23:21:23:21 | x | test.cpp:23:14:23:14 | x | is not null | is valid |
|
||||
| test.cpp:24:9:24:18 | (condition decl) | test.cpp:5:13:5:13 | v | is not null | is not valid |
|
||||
| test.cpp:24:9:24:18 | (condition decl) | test.cpp:24:14:24:14 | y | is not null | is valid |
|
||||
@@ -0,0 +1,8 @@
|
||||
import cpp
|
||||
|
||||
from AnalysedExpr a, LocalScopeVariable v, string isNullCheck, string isValidCheck
|
||||
where
|
||||
v.getAnAccess().getEnclosingStmt() = a.getParent() and
|
||||
(if a.isNullCheck(v) then isNullCheck = "is null" else isNullCheck = "is not null") and
|
||||
(if a.isValidCheck(v) then isValidCheck = "is valid" else isValidCheck = "is not valid")
|
||||
select a, v, isNullCheck, isValidCheck
|
||||
25
cpp/ql/test/library-tests/controlflow/nullness/test.cpp
Normal file
25
cpp/ql/test/library-tests/controlflow/nullness/test.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
// semmle-extractor-options: -std=c++17
|
||||
|
||||
long __builtin_expect(long);
|
||||
|
||||
void f(int *v) {
|
||||
int *w;
|
||||
bool b, c;
|
||||
|
||||
if (v) {}
|
||||
if (!v) {}
|
||||
if (v == 0) {}
|
||||
if ((!v) == 0) {}
|
||||
if (v != 0) {}
|
||||
if ((!v) != 0) {}
|
||||
if(__builtin_expect((long)v)) {}
|
||||
if(__builtin_expect((long)!v)) {}
|
||||
if (true && v) {}
|
||||
if (v && true) {}
|
||||
if (true && !v) {}
|
||||
if (!v && true) {}
|
||||
if (b = !v) {}
|
||||
if (c = !v; c) {}
|
||||
if (int *x = v; x) {}
|
||||
if (int *y = v) {}
|
||||
}
|
||||
@@ -4,11 +4,7 @@
|
||||
| c.c:6:5:6:6 | ls | array of 4 {int} | 1 |
|
||||
| c.c:8:5:8:7 | iss | array of 4 {array of 2 {int}} | 1 |
|
||||
| c.c:12:11:12:11 | i | typedef {int} as "int_alias" | 1 |
|
||||
| c.h:4:12:4:13 | ks | array of {int} | 1 |
|
||||
| c.h:8:12:8:14 | iss | array of {array of 2 {int}} | 1 |
|
||||
| c.h:10:12:10:12 | i | int | 1 |
|
||||
| d.cpp:3:7:3:8 | xs | array of {int} | 1 |
|
||||
| d.h:3:14:3:15 | xs | array of 2 {int} | 1 |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | reference to {const {struct __va_list_tag}} | 1 |
|
||||
| file://:0:0:0:0 | (unnamed parameter 0) | rvalue reference to {struct __va_list_tag} | 1 |
|
||||
| file://:0:0:0:0 | fp_offset | unsigned int | 1 |
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
| vector_types2.cpp:10:15:10:42 | __builtin_shuffle |
|
||||
| vector_types2.cpp:11:15:11:45 | __builtin_shuffle |
|
||||
| vector_types.cpp:31:13:31:49 | __builtin_shufflevector |
|
||||
| vector_types.cpp:58:10:58:52 | __builtin_convertvector |
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
| file://:0:0:0:0 | gp_offset | gp_offset | file://:0:0:0:0 | unsigned int | 4 |
|
||||
| file://:0:0:0:0 | overflow_arg_area | overflow_arg_area | file://:0:0:0:0 | void * | 8 |
|
||||
| file://:0:0:0:0 | reg_save_area | reg_save_area | file://:0:0:0:0 | void * | 8 |
|
||||
| vector_types2.cpp:5:7:5:7 | a | a | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types2.cpp:6:7:6:7 | b | b | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types2.cpp:7:7:7:12 | mask_1 | mask_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types2.cpp:8:7:8:12 | mask_2 | mask_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types2.cpp:10:7:10:11 | res_1 | res_1 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types2.cpp:11:7:11:11 | res_2 | res_2 | vector_types2.cpp:2:13:2:15 | v4i | 16 |
|
||||
| vector_types.cpp:9:21:9:21 | x | x | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||
| vector_types.cpp:14:18:14:20 | lhs | lhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||
| vector_types.cpp:14:27:14:29 | rhs | rhs | vector_types.cpp:6:15:6:17 | v4f | 16 |
|
||||
|
||||
12
cpp/ql/test/library-tests/vector_types/vector_types2.cpp
Normal file
12
cpp/ql/test/library-tests/vector_types/vector_types2.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
// semmle-extractor-options: --gnu --gnu_version 80000
|
||||
typedef int v4i __attribute__((vector_size (16)));
|
||||
|
||||
void f() {
|
||||
v4i a = {1,2,3,4};
|
||||
v4i b = {5,6,7,8};
|
||||
v4i mask_1 = {3,0,1,2};
|
||||
v4i mask_2 = {3,5,4,2};
|
||||
|
||||
v4i res_1 = __builtin_shuffle(a, mask_1);
|
||||
v4i res_2 = __builtin_shuffle(a, b, mask_2);
|
||||
}
|
||||
Reference in New Issue
Block a user