C#: Add more copies of the data flow library

This commit is contained in:
Tom Hvitved
2019-08-05 15:52:32 +02:00
parent d0a761477b
commit 081ee9944d
11 changed files with 7715 additions and 3 deletions

View File

@@ -1,5 +1,5 @@
{
"DataFlow Java/C++": [
"DataFlow Java/C++/C#": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll",
@@ -13,9 +13,13 @@
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll"
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
"csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll"
],
"DataFlow Java/C++ Common": [
"DataFlow Java/C++/C# Common": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",

View File

@@ -7,4 +7,23 @@ import csharp
module DataFlow {
import semmle.code.csharp.dataflow.internal.DataFlowImpl
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
abstract private class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0 or
strictcount(Node n | this.isSink(n)) < 0 or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) data flow analyses.
*/
import csharp
module DataFlow2 {
import semmle.code.csharp.dataflow.internal.DataFlowImpl2
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
abstract private class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0 or
strictcount(Node n | this.isSink(n)) < 0 or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) data flow analyses.
*/
import csharp
module DataFlow3 {
import semmle.code.csharp.dataflow.internal.DataFlowImpl3
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
abstract private class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0 or
strictcount(Node n | this.isSink(n)) < 0 or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) data flow analyses.
*/
import csharp
module DataFlow4 {
import semmle.code.csharp.dataflow.internal.DataFlowImpl4
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
abstract private class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0 or
strictcount(Node n | this.isSink(n)) < 0 or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,29 @@
/**
* Provides classes for performing local (intra-procedural) and
* global (inter-procedural) data flow analyses.
*/
import csharp
module DataFlow5 {
import semmle.code.csharp.dataflow.internal.DataFlowImpl5
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
abstract private class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0 or
strictcount(Node n | this.isSink(n)) < 0 or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 or
super.hasFlow(source, sink)
}
}
}

View File

@@ -6,6 +6,11 @@
import csharp
module TaintTracking {
private import semmle.code.csharp.dataflow.DataFlow
private import semmle.code.csharp.dataflow.DataFlow2
private import semmle.code.csharp.dataflow.DataFlow3
private import semmle.code.csharp.dataflow.DataFlow4
private import semmle.code.csharp.dataflow.DataFlow5
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.ControlFlowReachability
@@ -99,6 +104,258 @@ module TaintTracking {
}
}
/**
* A taint tracking configuration.
*
* A taint tracking configuration is a special dataflow configuration
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
* necessarily preserve values, but are still relevant from a taint tracking
* perspective. (For example, string concatenation, where one of the operands
* is tainted.)
*
* Each use of the taint tracking library must define its own unique extension
* of this abstract class. A configuration defines a set of relevant sources
* (`isSource`) and sinks (`isSink`), and may additionally treat intermediate
* nodes as "sanitizers" (`isSanitizer`) as well as add custom taint flow steps
* (`isAdditionalTaintStep()`).
*/
abstract class Configuration2 extends DataFlow2::Configuration {
bindingset[this]
Configuration2() { any() }
/**
* Holds if `source` is a relevant taint source.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSource(DataFlow::Node source);
/**
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSink(DataFlow::Node sink);
/** Holds if the intermediate node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
/**
* Holds if the additional taint propagation step from `pred` to `succ`
* must be taken into account in the analysis.
*/
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ)
or
localAdditionalTaintStep(pred, succ)
or
succ = pred.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
// overridden to provide taint-tracking specific qldoc
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
super.hasFlow(source, sink)
}
}
/**
* A taint tracking configuration.
*
* A taint tracking configuration is a special dataflow configuration
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
* necessarily preserve values, but are still relevant from a taint tracking
* perspective. (For example, string concatenation, where one of the operands
* is tainted.)
*
* Each use of the taint tracking library must define its own unique extension
* of this abstract class. A configuration defines a set of relevant sources
* (`isSource`) and sinks (`isSink`), and may additionally treat intermediate
* nodes as "sanitizers" (`isSanitizer`) as well as add custom taint flow steps
* (`isAdditionalTaintStep()`).
*/
abstract class Configuration3 extends DataFlow3::Configuration {
bindingset[this]
Configuration3() { any() }
/**
* Holds if `source` is a relevant taint source.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSource(DataFlow::Node source);
/**
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSink(DataFlow::Node sink);
/** Holds if the intermediate node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
/**
* Holds if the additional taint propagation step from `pred` to `succ`
* must be taken into account in the analysis.
*/
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ)
or
localAdditionalTaintStep(pred, succ)
or
succ = pred.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
// overridden to provide taint-tracking specific qldoc
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
super.hasFlow(source, sink)
}
}
/**
* A taint tracking configuration.
*
* A taint tracking configuration is a special dataflow configuration
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
* necessarily preserve values, but are still relevant from a taint tracking
* perspective. (For example, string concatenation, where one of the operands
* is tainted.)
*
* Each use of the taint tracking library must define its own unique extension
* of this abstract class. A configuration defines a set of relevant sources
* (`isSource`) and sinks (`isSink`), and may additionally treat intermediate
* nodes as "sanitizers" (`isSanitizer`) as well as add custom taint flow steps
* (`isAdditionalTaintStep()`).
*/
abstract class Configuration4 extends DataFlow4::Configuration {
bindingset[this]
Configuration4() { any() }
/**
* Holds if `source` is a relevant taint source.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSource(DataFlow::Node source);
/**
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSink(DataFlow::Node sink);
/** Holds if the intermediate node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
/**
* Holds if the additional taint propagation step from `pred` to `succ`
* must be taken into account in the analysis.
*/
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ)
or
localAdditionalTaintStep(pred, succ)
or
succ = pred.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
// overridden to provide taint-tracking specific qldoc
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
super.hasFlow(source, sink)
}
}
/**
* A taint tracking configuration.
*
* A taint tracking configuration is a special dataflow configuration
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
* necessarily preserve values, but are still relevant from a taint tracking
* perspective. (For example, string concatenation, where one of the operands
* is tainted.)
*
* Each use of the taint tracking library must define its own unique extension
* of this abstract class. A configuration defines a set of relevant sources
* (`isSource`) and sinks (`isSink`), and may additionally treat intermediate
* nodes as "sanitizers" (`isSanitizer`) as well as add custom taint flow steps
* (`isAdditionalTaintStep()`).
*/
abstract class Configuration5 extends DataFlow5::Configuration {
bindingset[this]
Configuration5() { any() }
/**
* Holds if `source` is a relevant taint source.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSource(DataFlow::Node source);
/**
* Holds if `sink` is a relevant taint sink.
*
* The smaller this predicate is, the faster `hasFlow()` will converge.
*/
// overridden to provide taint-tracking specific qldoc
abstract override predicate isSink(DataFlow::Node sink);
/** Holds if the intermediate node `node` is a taint sanitizer. */
predicate isSanitizer(DataFlow::Node node) { none() }
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
/**
* Holds if the additional taint propagation step from `pred` to `succ`
* must be taken into account in the analysis.
*/
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ)
or
localAdditionalTaintStep(pred, succ)
or
succ = pred.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
// overridden to provide taint-tracking specific qldoc
override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) {
super.hasFlow(source, sink)
}
}
/** INTERNAL: Do not use. */
module Internal {
private CIL::DataFlowNode asCilDataFlowNode(DataFlow::Node node) {

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

File diff suppressed because it is too large Load Diff