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,9 @@
|
||||
## 0.2.3
|
||||
|
||||
### New Features
|
||||
|
||||
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||
|
||||
## 0.2.2
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* `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.2.3.md
Normal file
5
cpp/ql/lib/change-notes/released/0.2.3.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.2.3
|
||||
|
||||
### New Features
|
||||
|
||||
* An `isBraced` predicate was added to the `Initializer` class which holds when a C++ braced initializer was used in the initialization.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.2.2
|
||||
lastReleaseVersion: 0.2.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.2.3-dev
|
||||
version: 0.3.0-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -48,8 +48,8 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
|
||||
}
|
||||
|
||||
override TypeDeclarationEntry getADeclarationEntry() {
|
||||
if type_decls(_, underlyingElement(this), _)
|
||||
then type_decls(unresolveElement(result), underlyingElement(this), _)
|
||||
if type_decls(_, unresolveElement(this), _)
|
||||
then type_decls(underlyingElement(result), unresolveElement(this), _)
|
||||
else exists(Class t | this.(Class).isConstructedFrom(t) and result = t.getADeclarationEntry())
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -850,6 +850,34 @@ class ContentSet instanceof Content {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||
*
|
||||
* The expression `e` is expected to be a syntactic part of the guard `g`.
|
||||
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||
* the argument `x`.
|
||||
*/
|
||||
signature predicate guardChecksSig(GuardCondition g, Expr e, boolean branch);
|
||||
|
||||
/**
|
||||
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||
*
|
||||
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||
* in data flow and taint tracking.
|
||||
*/
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
ExprNode getABarrierNode() {
|
||||
exists(GuardCondition g, SsaDefinition def, Variable v, boolean branch |
|
||||
result.getExpr() = def.getAUse(v) and
|
||||
guardChecks(g, def.getAUse(v), branch) and
|
||||
g.controls(result.getExpr().getBasicBlock(), branch)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||
*
|
||||
* A guard that validates some expression.
|
||||
*
|
||||
* To use this in a configuration, extend the class and provide a
|
||||
@@ -858,7 +886,7 @@ class ContentSet instanceof Content {
|
||||
*
|
||||
* It is important that all extending classes in scope are disjoint.
|
||||
*/
|
||||
class BarrierGuard extends GuardCondition {
|
||||
deprecated class BarrierGuard extends GuardCondition {
|
||||
/** Override this predicate to hold if this guard validates `e` upon evaluating to `b`. */
|
||||
abstract predicate checks(Expr e, boolean b);
|
||||
|
||||
|
||||
@@ -47,12 +47,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||
|
||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
* qualified.
|
||||
*
|
||||
* This file contains classes that mirror the standard AST classes for C++, but
|
||||
* these classes are only concerned with naming. The other difference is that
|
||||
* these classes don't use the `ResolveClass.qll` mechanisms like
|
||||
* `unresolveElement` because these classes should eventually be part of the
|
||||
* implementation of `ResolveClass.qll`, allowing it to match up classes when
|
||||
* their qualified names and parameters match.
|
||||
* these classes are only concerned with naming.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.Declaration as D
|
||||
|
||||
@@ -115,15 +115,13 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate isClass(@usertype t) {
|
||||
(
|
||||
usertypes(t, _, 1) or
|
||||
usertypes(t, _, 2) or
|
||||
usertypes(t, _, 3) or
|
||||
usertypes(t, _, 6) or
|
||||
usertypes(t, _, 10) or
|
||||
usertypes(t, _, 11) or
|
||||
usertypes(t, _, 12)
|
||||
)
|
||||
usertypes(t, _, 1) or
|
||||
usertypes(t, _, 2) or
|
||||
usertypes(t, _, 3) or
|
||||
usertypes(t, _, 6) or
|
||||
usertypes(t, _, 10) or
|
||||
usertypes(t, _, 11) or
|
||||
usertypes(t, _, 12)
|
||||
}
|
||||
|
||||
cached
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -90,14 +90,20 @@ abstract class Configuration extends string {
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/** Holds if data flow through nodes guarded by `guard` is prohibited. */
|
||||
predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if data flow through nodes guarded by `guard` is prohibited when
|
||||
* the flow state is `state`
|
||||
*/
|
||||
predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
@@ -335,6 +341,29 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
/** A bridge class to access the deprecated `isBarrierGuard`. */
|
||||
private class BarrierGuardGuardedNodeBridge extends Unit {
|
||||
abstract predicate guardedNode(Node n, Configuration config);
|
||||
|
||||
abstract predicate guardedNode(Node n, FlowState state, Configuration config);
|
||||
}
|
||||
|
||||
private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge {
|
||||
deprecated override predicate guardedNode(Node n, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) {
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
@@ -348,10 +377,7 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
not config.isSink(n) and
|
||||
not config.isSink(n, _)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -360,10 +386,7 @@ private predicate stateBarrier(NodeEx node, FlowState state, Configuration confi
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n, state)
|
||||
or
|
||||
exists(BarrierGuard g |
|
||||
config.isBarrierGuard(g, state) and
|
||||
n = g.getAGuardedNode()
|
||||
)
|
||||
any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1092,6 +1092,56 @@ class ContentSet instanceof Content {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
|
||||
*
|
||||
* The expression `e` is expected to be a syntactic part of the guard `g`.
|
||||
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||
* the argument `x`.
|
||||
*/
|
||||
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
|
||||
|
||||
/**
|
||||
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||
*
|
||||
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||
* in data flow and taint tracking.
|
||||
*/
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
result.asInstruction() = value.getAnInstruction() and
|
||||
g.controls(result.asInstruction().getBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
|
||||
*/
|
||||
signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch);
|
||||
|
||||
/**
|
||||
* Provides a set of barrier nodes for a guard that validates an instruction.
|
||||
*
|
||||
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||
* in data flow and taint tracking.
|
||||
*/
|
||||
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, ValueNumber value, boolean edge |
|
||||
instructionGuardChecks(g, value.getAnInstruction(), edge) and
|
||||
result.asInstruction() = value.getAnInstruction() and
|
||||
g.controls(result.asInstruction().getBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BarrierGuard` module instead.
|
||||
*
|
||||
* A guard that validates some instruction.
|
||||
*
|
||||
* To use this in a configuration, extend the class and provide a
|
||||
@@ -1100,7 +1150,7 @@ class ContentSet instanceof Content {
|
||||
*
|
||||
* It is important that all extending classes in scope are disjoint.
|
||||
*/
|
||||
class BarrierGuard extends IRGuardCondition {
|
||||
deprecated 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() }
|
||||
|
||||
|
||||
@@ -94,12 +94,6 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
|
||||
or
|
||||
exists(DataFlow::BarrierGuard guard |
|
||||
any(DataFlow::Configuration cfg).isBarrierGuard(guard) and
|
||||
node = guard.getAGuardedNode() and
|
||||
kind = "guard(" + guard.getResultId() + ")"
|
||||
)
|
||||
|
|
||||
kind, ", "
|
||||
)
|
||||
|
||||
@@ -163,12 +163,6 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
|
||||
* modeled function.
|
||||
|
||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -116,20 +116,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited.
|
||||
*/
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead.
|
||||
*
|
||||
* Holds if taint propagation through nodes guarded by `guard` is prohibited
|
||||
* when the flow state is `state`.
|
||||
*/
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { none() }
|
||||
deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) {
|
||||
deprecated final override predicate isBarrierGuard(
|
||||
DataFlow::BarrierGuard guard, DataFlow::FlowState state
|
||||
) {
|
||||
this.isSanitizerGuard(guard, state)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
## 0.1.4
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
1
cpp/ql/src/change-notes/released/0.1.4.md
Normal file
1
cpp/ql/src/change-notes/released/0.1.4.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.1.4
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.3
|
||||
lastReleaseVersion: 0.1.4
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
...
|
||||
SSL_shutdown(ssl);
|
||||
SSL_shutdown(ssl); // BAD
|
||||
...
|
||||
switch ((ret = SSL_shutdown(ssl))) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
ERR_clear_error();
|
||||
if (-1 != (ret = SSL_shutdown(ssl))) break; // GOOD
|
||||
...
|
||||
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<example>
|
||||
<p>The following example shows the incorrect and correct usage of function SSL_shutdown.</p>
|
||||
<sample src="DangerousUseSSL_shutdown.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP12-C.+Do+not+ignore+values+returned+by+functions">EXP12-C. Do not ignore values returned by functions - SEI CERT C Coding Standard - Confluence</a>.
|
||||
</li>
|
||||
<li>
|
||||
Openssl.org:
|
||||
<a href="https://www.openssl.org/docs/man3.0/man3/SSL_shutdown.html">SSL_shutdown - shut down a TLS/SSL connection</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @name Dangerous use SSL_shutdown.
|
||||
* @description Incorrect closing of the connection leads to the creation of different states for the server and client, which can be exploited by an attacker.
|
||||
* @kind problem
|
||||
* @id cpp/dangerous-use-of-ssl-shutdown
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-670
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Exclusions
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
|
||||
from FunctionCall fc, FunctionCall fc1
|
||||
where
|
||||
fc != fc1 and
|
||||
fc.getASuccessor+() = fc1 and
|
||||
fc.getTarget().hasName("SSL_shutdown") and
|
||||
fc1.getTarget().hasName("SSL_shutdown") and
|
||||
fc1 instanceof ExprInVoidContext and
|
||||
(
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fc1.getArgument(0)) or
|
||||
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget()
|
||||
) and
|
||||
not exists(FunctionCall fctmp |
|
||||
fctmp.getTarget().hasName("SSL_free") and
|
||||
fc.getASuccessor+() = fctmp and
|
||||
fctmp.getASuccessor+() = fc1
|
||||
)
|
||||
select fc, "You need to handle the return value SSL_shutdown"
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.1.4-dev
|
||||
version: 0.2.0-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -239,12 +239,24 @@ private string getColumnString(TColumn column) {
|
||||
|
||||
/**
|
||||
* RegEx pattern to match a single expected result, not including the leading `$`. It consists of one or
|
||||
* more comma-separated tags containing only letters, digits, `-` and `_` (note that the first character
|
||||
* must not be a digit), optionally followed by `=` and the expected value.
|
||||
* more comma-separated tags optionally followed by `=` and the expected value.
|
||||
*
|
||||
* Tags must be only letters, digits, `-` and `_` (note that the first character
|
||||
* must not be a digit), but can contain anything enclosed in a single set of
|
||||
* square brackets.
|
||||
*
|
||||
* Examples:
|
||||
* - `tag`
|
||||
* - `tag=value`
|
||||
* - `tag,tag2=value`
|
||||
* - `tag[foo bar]=value`
|
||||
*
|
||||
* Not allowed:
|
||||
* - `tag[[[foo bar]`
|
||||
*/
|
||||
private string expectationPattern() {
|
||||
exists(string tag, string tags, string value |
|
||||
tag = "[A-Za-z-_][A-Za-z-_0-9]*" and
|
||||
tag = "[A-Za-z-_](?:[A-Za-z-_0-9]|\\[[^\\]\\]]*\\])*" and
|
||||
tags = "((?:" + tag + ")(?:\\s*,\\s*" + tag + ")*)" and
|
||||
// In Python, we allow both `"` and `'` for strings, as well as the prefixes `bru`.
|
||||
// For example, `b"foo"`.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.cpp:45:20:45:31 | call to SSL_shutdown | You need to handle the return value SSL_shutdown |
|
||||
| test.cpp:61:11:61:22 | call to SSL_shutdown | You need to handle the return value SSL_shutdown |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-670/DangerousUseSSL_shutdown.ql
|
||||
@@ -0,0 +1,75 @@
|
||||
// it's not exact, but it's enough for an example
|
||||
typedef int SSL;
|
||||
|
||||
|
||||
int SSL_shutdown(SSL *ssl);
|
||||
int SSL_get_error(const SSL *ssl, int ret);
|
||||
void ERR_clear_error(void);
|
||||
void print_error(char *buff,int code);
|
||||
|
||||
int gootTest1(SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
switch ((ret = SSL_shutdown(ssl))) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
ERR_clear_error();
|
||||
if ((ret = SSL_shutdown(ssl)) == 1) break; // GOOD
|
||||
default:
|
||||
print_error("error shutdown",
|
||||
SSL_get_error(ssl, ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int gootTest2(SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
switch ((ret = SSL_shutdown(ssl))) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
ERR_clear_error();
|
||||
if (-1 != (ret = SSL_shutdown(ssl))) break; // GOOD
|
||||
default:
|
||||
print_error("error shutdown",
|
||||
SSL_get_error(ssl, ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int badTest1(SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
switch ((ret = SSL_shutdown(ssl))) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
SSL_shutdown(ssl); // BAD
|
||||
break;
|
||||
default:
|
||||
print_error("error shutdown",
|
||||
SSL_get_error(ssl, ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int badTest2(SSL *ssl)
|
||||
{
|
||||
int ret;
|
||||
ret = SSL_shutdown(ssl);
|
||||
switch (ret) {
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
SSL_shutdown(ssl); // BAD
|
||||
break;
|
||||
default:
|
||||
print_error("error shutdown",
|
||||
SSL_get_error(ssl, ret));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -220,10 +220,10 @@ postWithInFlow
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:15:23:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -2,19 +2,17 @@ import TestUtilities.dataflow.FlowTestCommon
|
||||
|
||||
module AstTest {
|
||||
private import semmle.code.cpp.dataflow.DataFlow
|
||||
private import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
class TestBarrierGuard extends DataFlow::BarrierGuard {
|
||||
TestBarrierGuard() { this.(FunctionCall).getTarget().getName() = "guarded" }
|
||||
|
||||
override predicate checks(Expr checked, boolean isTrue) {
|
||||
checked = this.(FunctionCall).getArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
|
||||
g.(FunctionCall).getTarget().getName() = "guarded" and
|
||||
checked = g.(FunctionCall).getArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
@@ -40,29 +38,26 @@ module AstTest {
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier")
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
}
|
||||
|
||||
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
|
||||
}
|
||||
}
|
||||
|
||||
module IRTest {
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
class TestBarrierGuard extends DataFlow::BarrierGuard {
|
||||
TestBarrierGuard() { this.(CallInstruction).getStaticCallTarget().getName() = "guarded" }
|
||||
|
||||
override predicate checksInstr(Instruction checked, boolean isTrue) {
|
||||
checked = this.(CallInstruction).getPositionalArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
predicate testBarrierGuard(IRGuardCondition g, Instruction checked, boolean isTrue) {
|
||||
g.(CallInstruction).getStaticCallTarget().getName() = "guarded" and
|
||||
checked = g.(CallInstruction).getPositionalArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
@@ -93,10 +88,9 @@ module IRTest {
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier")
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
|
||||
barrier = DataFlow::InstructionBarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
}
|
||||
|
||||
override predicate isBarrierGuard(DataFlow::BarrierGuard bg) { bg instanceof TestBarrierGuard }
|
||||
}
|
||||
|
||||
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
|
||||
@@ -33,3 +33,11 @@ public:
|
||||
|
||||
myTemplateClass<int> mtc_int;
|
||||
myTemplateClass<short> mtc_short;
|
||||
|
||||
// Class (UserType)
|
||||
|
||||
class myClass
|
||||
{
|
||||
public:
|
||||
int myMemberVariable;
|
||||
};
|
||||
|
||||
@@ -27,5 +27,11 @@
|
||||
| declarationEntry.cpp:31:4:31:19 | myMemberVariable | declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | 1 | 1 |
|
||||
| declarationEntry.cpp:34:22:34:28 | mtc_int | declarationEntry.cpp:34:22:34:28 | definition of mtc_int | 1 | 1 |
|
||||
| declarationEntry.cpp:35:24:35:32 | mtc_short | declarationEntry.cpp:35:24:35:32 | definition of mtc_short | 1 | 1 |
|
||||
| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 |
|
||||
| declarationEntry.cpp:39:7:39:7 | operator= | declarationEntry.cpp:39:7:39:7 | declaration of operator= | 1 | 1 |
|
||||
| declarationEntry.cpp:39:7:39:13 | myClass | declarationEntry.cpp:39:7:39:13 | definition of myClass | 1 | 1 |
|
||||
| declarationEntry.cpp:39:7:39:13 | myClass | forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | 1 | 1 |
|
||||
| declarationEntry.cpp:42:6:42:21 | myMemberVariable | declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | 1 | 1 |
|
||||
| forwardDeclaration.cpp:3:10:3:19 | myClassPtr | forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | 1 | 1 |
|
||||
| macro.c:2:1:2:3 | foo | macro.c:2:1:2:3 | declaration of foo | 1 | 1 |
|
||||
| macro.c:4:5:4:8 | main | macro.c:4:5:4:8 | definition of main | 1 | 1 |
|
||||
|
||||
@@ -10,5 +10,7 @@
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
|
||||
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
|
||||
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
|
||||
| macro.c:2:1:2:3 | declaration of foo | | 2 | c_linkage, static |
|
||||
| macro.c:4:5:4:8 | definition of main | | 1 | c_linkage |
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class myClass;
|
||||
|
||||
myClass *myClassPtr;
|
||||
@@ -0,0 +1,45 @@
|
||||
| declarationEntry.c:2:6:2:20 | declaration of myFirstFunction | declarationEntry.c:2:6:2:20 | myFirstFunction | yes |
|
||||
| declarationEntry.c:4:6:4:21 | definition of mySecondFunction | declarationEntry.c:4:6:4:21 | mySecondFunction | yes |
|
||||
| declarationEntry.c:8:6:8:20 | definition of myThirdFunction | declarationEntry.c:8:6:8:20 | myThirdFunction | yes |
|
||||
| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes |
|
||||
| declarationEntry.c:13:2:13:2 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes |
|
||||
| declarationEntry.c:14:2:14:2 | declaration of myFifthFunction | declarationEntry.c:14:2:14:2 | myFifthFunction | yes |
|
||||
| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:13:2:13:2 | myFourthFunction | yes |
|
||||
| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | declarationEntry.c:17:6:17:21 | myFourthFunction | yes |
|
||||
| declarationEntry.cpp:3:12:3:21 | declaration of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes |
|
||||
| declarationEntry.cpp:5:5:5:14 | definition of myVariable | declarationEntry.cpp:5:5:5:14 | myVariable | yes |
|
||||
| declarationEntry.cpp:9:6:9:15 | declaration of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes |
|
||||
| declarationEntry.cpp:9:21:9:31 | declaration of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes |
|
||||
| declarationEntry.cpp:11:6:11:15 | definition of myFunction | declarationEntry.cpp:11:6:11:15 | myFunction | yes |
|
||||
| declarationEntry.cpp:11:21:11:31 | definition of myParameter | declarationEntry.cpp:11:21:11:31 | myParameter | yes |
|
||||
| declarationEntry.cpp:18:6:18:11 | declaration of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
|
||||
| declarationEntry.cpp:20:6:20:11 | definition of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
|
||||
| declarationEntry.cpp:27:20:27:20 | definition of T | declarationEntry.cpp:27:20:27:20 | T | yes |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
|
||||
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
|
||||
| declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | declarationEntry.cpp:28:7:28:21 | myTemplateClass<T> | yes |
|
||||
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
|
||||
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
|
||||
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
|
||||
| declarationEntry.cpp:34:22:34:28 | definition of mtc_int | declarationEntry.cpp:34:22:34:28 | mtc_int | yes |
|
||||
| declarationEntry.cpp:35:24:35:32 | definition of mtc_short | declarationEntry.cpp:35:24:35:32 | mtc_short | yes |
|
||||
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
|
||||
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | declarationEntry.cpp:39:7:39:7 | operator= | yes |
|
||||
| declarationEntry.cpp:39:7:39:13 | definition of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
|
||||
| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
|
||||
| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes |
|
||||
| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes |
|
||||
| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes |
|
||||
| file://:0:0:0:0 | definition of reg_save_area | file://:0:0:0:0 | reg_save_area | yes |
|
||||
| forwardDeclaration.cpp:1:7:1:13 | declaration of myClass | declarationEntry.cpp:39:7:39:13 | myClass | yes |
|
||||
| forwardDeclaration.cpp:3:10:3:19 | definition of myClassPtr | forwardDeclaration.cpp:3:10:3:19 | myClassPtr | yes |
|
||||
| macro.c:2:1:2:3 | declaration of foo | macro.c:2:1:2:3 | foo | yes |
|
||||
| macro.c:4:5:4:8 | definition of main | macro.c:4:5:4:8 | main | yes |
|
||||
@@ -0,0 +1,7 @@
|
||||
import cpp
|
||||
|
||||
from DeclarationEntry de, Declaration d, string canRoundTrip
|
||||
where
|
||||
d = de.getDeclaration() and
|
||||
if d.getADeclarationEntry() = de then canRoundTrip = "yes" else canRoundTrip = "no"
|
||||
select de, d, canRoundTrip
|
||||
@@ -4841,6 +4841,9 @@
|
||||
| ir.cpp:1043:24:1043:24 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:31:1043:31 | Address | &:r1043_9 |
|
||||
| ir.cpp:1043:36:1043:55 | Address | &:r1043_11 |
|
||||
| ir.cpp:1043:43:1043:43 | Address | &:r1043_16 |
|
||||
| ir.cpp:1043:43:1043:43 | Arg(this) | this:r1043_16 |
|
||||
| ir.cpp:1043:43:1043:43 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_22 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_24 |
|
||||
| ir.cpp:1043:43:1043:54 | Address | &:r1043_25 |
|
||||
@@ -4861,11 +4864,8 @@
|
||||
| ir.cpp:1043:45:1043:49 | SideEffect | ~m1043_4 |
|
||||
| ir.cpp:1043:45:1043:49 | Unary | r1043_13 |
|
||||
| ir.cpp:1043:45:1043:49 | Unary | r1043_15 |
|
||||
| ir.cpp:1043:52:1043:52 | Address | &:r1043_16 |
|
||||
| ir.cpp:1043:52:1043:52 | Arg(this) | this:r1043_16 |
|
||||
| ir.cpp:1043:52:1043:52 | SideEffect | ~m1043_20 |
|
||||
| ir.cpp:1043:54:1043:54 | Load | ~m1043_20 |
|
||||
| ir.cpp:1043:54:1043:54 | Right | r1043_26 |
|
||||
| ir.cpp:1043:53:1043:53 | Load | ~m1043_20 |
|
||||
| ir.cpp:1043:53:1043:53 | Right | r1043_26 |
|
||||
| ir.cpp:1043:58:1043:58 | ChiPartial | partial:m1043_9 |
|
||||
| ir.cpp:1043:58:1043:58 | ChiTotal | total:m1043_3 |
|
||||
| ir.cpp:1043:58:1043:58 | StoreValue | r1043_8 |
|
||||
@@ -4980,6 +4980,9 @@
|
||||
| ir.cpp:1047:34:1047:34 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:41:1047:41 | Address | &:r1047_9 |
|
||||
| ir.cpp:1047:46:1047:65 | Address | &:r1047_11 |
|
||||
| ir.cpp:1047:53:1047:53 | Address | &:r1047_16 |
|
||||
| ir.cpp:1047:53:1047:53 | Arg(this) | this:r1047_16 |
|
||||
| ir.cpp:1047:53:1047:53 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:53:1047:64 | Address | &:r1047_23 |
|
||||
| ir.cpp:1047:53:1047:64 | Load | ~m1047_20 |
|
||||
| ir.cpp:1047:53:1047:64 | StoreValue | r1047_24 |
|
||||
@@ -4994,9 +4997,6 @@
|
||||
| ir.cpp:1047:55:1047:59 | SideEffect | ~m1047_4 |
|
||||
| ir.cpp:1047:55:1047:59 | Unary | r1047_13 |
|
||||
| ir.cpp:1047:55:1047:59 | Unary | r1047_15 |
|
||||
| ir.cpp:1047:62:1047:62 | Address | &:r1047_16 |
|
||||
| ir.cpp:1047:62:1047:62 | Arg(this) | this:r1047_16 |
|
||||
| ir.cpp:1047:62:1047:62 | SideEffect | ~m1047_20 |
|
||||
| ir.cpp:1047:63:1047:63 | Right | r1047_22 |
|
||||
| ir.cpp:1047:68:1047:68 | StoreValue | r1047_8 |
|
||||
| ir.cpp:1047:68:1047:68 | Unary | r1047_7 |
|
||||
@@ -5105,6 +5105,9 @@
|
||||
| ir.cpp:1051:39:1051:39 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:46:1051:46 | Address | &:r1051_9 |
|
||||
| ir.cpp:1051:51:1051:70 | Address | &:r1051_11 |
|
||||
| ir.cpp:1051:58:1051:58 | Address | &:r1051_16 |
|
||||
| ir.cpp:1051:58:1051:58 | Arg(this) | this:r1051_16 |
|
||||
| ir.cpp:1051:58:1051:58 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_22 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_24 |
|
||||
| ir.cpp:1051:58:1051:69 | Address | &:r1051_26 |
|
||||
@@ -5125,9 +5128,6 @@
|
||||
| ir.cpp:1051:60:1051:64 | SideEffect | ~m1051_4 |
|
||||
| ir.cpp:1051:60:1051:64 | Unary | r1051_13 |
|
||||
| ir.cpp:1051:60:1051:64 | Unary | r1051_15 |
|
||||
| ir.cpp:1051:67:1051:67 | Address | &:r1051_16 |
|
||||
| ir.cpp:1051:67:1051:67 | Arg(this) | this:r1051_16 |
|
||||
| ir.cpp:1051:67:1051:67 | SideEffect | ~m1051_20 |
|
||||
| ir.cpp:1051:73:1051:73 | ChiPartial | partial:m1051_9 |
|
||||
| ir.cpp:1051:73:1051:73 | ChiTotal | total:m1051_3 |
|
||||
| ir.cpp:1051:73:1051:73 | StoreValue | r1051_8 |
|
||||
@@ -5192,6 +5192,9 @@
|
||||
| ir.cpp:1054:49:1054:49 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:56:1054:56 | Address | &:r1054_9 |
|
||||
| ir.cpp:1054:61:1054:88 | Address | &:r1054_11 |
|
||||
| ir.cpp:1054:68:1054:68 | Address | &:r1054_16 |
|
||||
| ir.cpp:1054:68:1054:68 | Arg(this) | this:r1054_16 |
|
||||
| ir.cpp:1054:68:1054:68 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:68:1054:87 | Address | &:r1054_37 |
|
||||
| ir.cpp:1054:68:1054:87 | Load | ~m1054_20 |
|
||||
| ir.cpp:1054:68:1054:87 | StoreValue | r1054_38 |
|
||||
@@ -5206,9 +5209,6 @@
|
||||
| ir.cpp:1054:70:1054:74 | SideEffect | ~m1054_4 |
|
||||
| ir.cpp:1054:70:1054:74 | Unary | r1054_13 |
|
||||
| ir.cpp:1054:70:1054:74 | Unary | r1054_15 |
|
||||
| ir.cpp:1054:77:1054:77 | Address | &:r1054_16 |
|
||||
| ir.cpp:1054:77:1054:77 | Arg(this) | this:r1054_16 |
|
||||
| ir.cpp:1054:77:1054:77 | SideEffect | ~m1054_20 |
|
||||
| ir.cpp:1054:78:1054:82 | Address | &:r1054_22 |
|
||||
| ir.cpp:1054:78:1054:82 | Address | &:r1054_24 |
|
||||
| ir.cpp:1054:78:1054:82 | Left | r1054_25 |
|
||||
|
||||
@@ -156,10 +156,10 @@
|
||||
| captures.cpp:23:12:23:16 | x |
|
||||
| captures.cpp:23:12:23:16 | y |
|
||||
| captures.cpp:23:12:23:20 | ... + ... |
|
||||
| captures.cpp:23:16:23:16 | (reference dereference) |
|
||||
| captures.cpp:23:16:23:16 | definition of y |
|
||||
| captures.cpp:23:16:23:16 | y |
|
||||
| captures.cpp:23:16:23:16 | y |
|
||||
| captures.cpp:23:18:23:18 | (reference dereference) |
|
||||
| captures.cpp:23:20:23:20 | z |
|
||||
| captures.cpp:26:3:26:24 | return ... |
|
||||
| captures.cpp:26:10:26:17 | (const lambda [] type at line 22, col. 19)... |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
#include "a.h"
|
||||
|
||||
#include "c.h"
|
||||
|
||||
12
cpp/ql/test/library-tests/variables/global/c.c
Normal file
12
cpp/ql/test/library-tests/variables/global/c.c
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
int js[] = { 1, 2, 3, 4 };
|
||||
|
||||
int ks[4] = { 1, 2, 3, 4 };
|
||||
|
||||
int ls[4] = { 1, 2, 3, 4 };
|
||||
|
||||
int iss[4][2] = { { 1, 2 }, { 3, 4 }, { 1, 2 }, { 3, 4 } };
|
||||
|
||||
typedef int int_alias;
|
||||
|
||||
int_alias i;
|
||||
10
cpp/ql/test/library-tests/variables/global/c.h
Normal file
10
cpp/ql/test/library-tests/variables/global/c.h
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
extern int js[];
|
||||
|
||||
extern int ks[];
|
||||
|
||||
extern int ls[4];
|
||||
|
||||
extern int iss[][2];
|
||||
|
||||
extern int i;
|
||||
4
cpp/ql/test/library-tests/variables/global/d.cpp
Normal file
4
cpp/ql/test/library-tests/variables/global/d.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
namespace aNameSpace {
|
||||
int xs[] = { 1, 2 };
|
||||
}
|
||||
4
cpp/ql/test/library-tests/variables/global/d.h
Normal file
4
cpp/ql/test/library-tests/variables/global/d.h
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
namespace aNameSpace {
|
||||
extern int xs[2];
|
||||
}
|
||||
2
cpp/ql/test/library-tests/variables/global/e.cpp
Normal file
2
cpp/ql/test/library-tests/variables/global/e.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
#include "d.h"
|
||||
@@ -1,5 +1,17 @@
|
||||
| a.c:4:5:4:6 | definition of is | array of {int} | 1 |
|
||||
| a.h:2:12:2:13 | declaration of is | array of 4 {int} | 1 |
|
||||
| c.c:2:5:2:6 | definition of js | array of {int} | 1 |
|
||||
| c.c:4:5:4:6 | definition of ks | array of 4 {int} | 1 |
|
||||
| c.c:6:5:6:6 | definition of ls | array of 4 {int} | 1 |
|
||||
| c.c:8:5:8:7 | definition of iss | array of 4 {array of 2 {int}} | 1 |
|
||||
| c.c:12:11:12:11 | definition of i | typedef {int} as "int_alias" | 1 |
|
||||
| c.h:2:12:2:13 | declaration of js | array of {int} | 1 |
|
||||
| c.h:4:12:4:13 | declaration of ks | array of {int} | 1 |
|
||||
| c.h:6:12:6:13 | declaration of ls | array of 4 {int} | 1 |
|
||||
| c.h:8:12:8:14 | declaration of iss | array of {array of 2 {int}} | 1 |
|
||||
| c.h:10:12:10:12 | declaration of i | int | 1 |
|
||||
| d.cpp:3:7:3:8 | definition of xs | array of {int} | 1 |
|
||||
| d.h:3:14:3:15 | declaration of xs | array of 2 {int} | 1 |
|
||||
| file://:0:0:0:0 | definition of fp_offset | unsigned int | 1 |
|
||||
| file://:0:0:0:0 | definition of gp_offset | unsigned int | 1 |
|
||||
| file://:0:0:0:0 | definition of overflow_arg_area | pointer to {void} | 1 |
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
| a.c:4:5:4:6 | is | array of {int} | 1 |
|
||||
| c.c:2:5:2:6 | js | array of {int} | 1 |
|
||||
| c.c:4:5:4:6 | ks | array of 4 {int} | 1 |
|
||||
| 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 |
|
||||
| file://:0:0:0:0 | gp_offset | unsigned int | 1 |
|
||||
| file://:0:0:0:0 | overflow_arg_area | pointer to {void} | 1 |
|
||||
|
||||
Reference in New Issue
Block a user