Skip to content

Commit 10076a6

Browse files
authored
Merge pull request github#1886 from jbj/ir-taint-shared
Approved by rdmarsh2
2 parents e71a39f + 6021b4f commit 10076a6

File tree

12 files changed

+345
-158
lines changed

12 files changed

+345
-158
lines changed

config/identical-files.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
"TaintTracking::Configuration Java/C++/C#": [
3030
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
3131
"cpp/ql/src/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
32+
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
33+
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
3234
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll",
3335
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll",
3436
"csharp/ql/src/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll",

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
*
1414
* To use global (interprocedural) data flow, extend the class
1515
* `DataFlow::Configuration` as documented on that class. To use local
16-
* (intraprocedural) data flow, invoke `DataFlow::localFlow` or
17-
* `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`.
16+
* (intraprocedural) data flow between expressions, call
17+
* `DataFlow::localExprFlow`. For more general cases of local data flow, call
18+
* `DataFlow::localFlow` or `DataFlow::localFlowStep` with arguments of type
19+
* `DataFlow::Node`.
1820
*/
1921

2022
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow2.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow3.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/DataFlow4.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
77
* `DataFlow4::Configuration`.
88
*
9-
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
9+
* See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation.
1010
*/
1111

1212
import cpp

cpp/ql/src/semmle/code/cpp/ir/dataflow/TaintTracking.qll

Lines changed: 11 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -6,166 +6,24 @@
66
* the information from the source is preserved at the sink. For example, taint
77
* propagates from `x` to `x + 100`, but it does not propagate from `x` to `x >
88
* 100` since we consider a single bit of information to be too little.
9+
*
10+
* To use global (interprocedural) taint tracking, extend the class
11+
* `TaintTracking::Configuration` as documented on that class. To use local
12+
* (intraprocedural) taint tracking between expressions, call
13+
* `TaintTracking::localExprTaint`. For more general cases of local taint
14+
* tracking, call `TaintTracking::localTaint` or
15+
* `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`.
916
*/
1017

1118
import semmle.code.cpp.ir.dataflow.DataFlow
1219
import semmle.code.cpp.ir.dataflow.DataFlow2
13-
private import semmle.code.cpp.ir.IR
1420

1521
module TaintTracking {
16-
/**
17-
* A configuration of interprocedural taint tracking analysis. This defines
18-
* sources, sinks, and any other configurable aspect of the analysis. Each
19-
* use of the taint tracking library must define its own unique extension of
20-
* this abstract class.
21-
*
22-
* A taint-tracking configuration is a special data flow configuration
23-
* (`DataFlow::Configuration`) that allows for flow through nodes that do not
24-
* necessarily preserve values but are still relevant from a taint-tracking
25-
* perspective. (For example, string concatenation, where one of the operands
26-
* is tainted.)
27-
*
28-
* To create a configuration, extend this class with a subclass whose
29-
* characteristic predicate is a unique singleton string. For example, write
30-
*
31-
* ```
32-
* class MyAnalysisConfiguration extends TaintTracking::Configuration {
33-
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
34-
* // Override `isSource` and `isSink`.
35-
* // Optionally override `isSanitizer`.
36-
* // Optionally override `isAdditionalTaintStep`.
37-
* }
38-
* ```
39-
*
40-
* Then, to query whether there is flow between some `source` and `sink`,
41-
* write
42-
*
43-
* ```
44-
* exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
45-
* ```
46-
*
47-
* Multiple configurations can coexist, but it is unsupported to depend on a
48-
* `TaintTracking::Configuration` or a `DataFlow::Configuration` in the
49-
* overridden predicates that define sources, sinks, or additional steps.
50-
* Instead, the dependency should go to a `TaintTracking::Configuration2` or
51-
* a `DataFlow{2,3,4}::Configuration`.
52-
*/
53-
abstract class Configuration extends DataFlow::Configuration {
54-
bindingset[this]
55-
Configuration() { any() }
56-
57-
/** Holds if `source` is a taint source. */
58-
// overridden to provide taint-tracking specific qldoc
59-
abstract override predicate isSource(DataFlow::Node source);
60-
61-
/** Holds if `sink` is a taint sink. */
62-
// overridden to provide taint-tracking specific qldoc
63-
abstract override predicate isSink(DataFlow::Node sink);
64-
65-
/**
66-
* Holds if taint should not flow into `node`.
67-
*/
68-
predicate isSanitizer(DataFlow::Node node) { none() }
69-
70-
/**
71-
* Holds if the additional taint propagation step
72-
* from `source` to `target` must be taken into account in the analysis.
73-
* This step will only be followed if `target` is not in the `isSanitizer`
74-
* predicate.
75-
*/
76-
predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node target) { none() }
77-
78-
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
79-
80-
final override predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node target) {
81-
this.isAdditionalTaintStep(source, target)
82-
or
83-
localTaintStep(source, target)
84-
}
85-
}
86-
87-
/**
88-
* A taint-tracking configuration that is backed by the `DataFlow2` library
89-
* instead of `DataFlow`. Use this class when taint-tracking configurations
90-
* or data-flow configurations must depend on each other.
91-
*
92-
* See `TaintTracking::Configuration` for the full documentation.
93-
*/
94-
abstract class Configuration2 extends DataFlow2::Configuration {
95-
bindingset[this]
96-
Configuration2() { any() }
97-
98-
/** Holds if `source` is a taint source. */
99-
// overridden to provide taint-tracking specific qldoc
100-
abstract override predicate isSource(DataFlow::Node source);
101-
102-
/** Holds if `sink` is a taint sink. */
103-
// overridden to provide taint-tracking specific qldoc
104-
abstract override predicate isSink(DataFlow::Node sink);
105-
106-
/**
107-
* Holds if taint should not flow into `node`.
108-
*/
109-
predicate isSanitizer(DataFlow::Node node) { none() }
110-
111-
/**
112-
* Holds if the additional taint propagation step
113-
* from `source` to `target` must be taken into account in the analysis.
114-
* This step will only be followed if `target` is not in the `isSanitizer`
115-
* predicate.
116-
*/
117-
predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node target) { none() }
118-
119-
final override predicate isBarrier(DataFlow::Node node) { isSanitizer(node) }
120-
121-
final override predicate isAdditionalFlowStep(DataFlow::Node source, DataFlow::Node target) {
122-
this.isAdditionalTaintStep(source, target)
123-
or
124-
localTaintStep(source, target)
125-
}
126-
}
127-
128-
/**
129-
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
130-
* (intra-procedural) step.
131-
*/
132-
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
133-
// Taint can flow into using ordinary data flow.
134-
DataFlow::localFlowStep(nodeFrom, nodeTo)
135-
or
136-
localInstructionTaintStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
137-
}
138-
139-
/**
140-
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
141-
* (intra-procedural) step.
142-
*/
143-
private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction nodeTo) {
144-
// Taint can flow through expressions that alter the value but preserve
145-
// more than one bit of it _or_ expressions that follow data through
146-
// pointer indirections.
147-
nodeTo.getAnOperand().getAnyDef() = nodeFrom and
148-
(
149-
nodeTo instanceof ArithmeticInstruction
150-
or
151-
nodeTo instanceof BitwiseInstruction
152-
or
153-
nodeTo instanceof PointerArithmeticInstruction
154-
or
155-
nodeTo instanceof FieldAddressInstruction
156-
or
157-
// The `CopyInstruction` case is also present in non-taint data flow, but
158-
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
159-
// from a definition of `myStruct` to a `myStruct.myField` expression.
160-
nodeTo instanceof CopyInstruction
161-
)
162-
or
163-
nodeTo.(LoadInstruction).getSourceAddress() = nodeFrom
164-
}
22+
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
23+
private import semmle.code.cpp.ir.dataflow.TaintTracking2
16524

16625
/**
167-
* Holds if taint may propagate from `source` to `sink` in zero or more local
168-
* (intra-procedural) steps.
26+
* DEPRECATED: Use TaintTracking2::Configuration instead.
16927
*/
170-
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
28+
deprecated class Configuration2 = TaintTracking2::Configuration;
17129
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Provides a `TaintTracking2` module, which is a copy of the `TaintTracking`
3+
* module. Use this class when data-flow configurations or taint-tracking
4+
* configurations must depend on each other. Two classes extending
5+
* `DataFlow::Configuration` should never depend on each other, but one of them
6+
* should instead depend on a `DataFlow2::Configuration`, a
7+
* `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. The
8+
* `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and
9+
* `TaintTracking2::Configuration` extends `DataFlow2::Configuration`.
10+
*
11+
* See `semmle.code.cpp.ir.dataflow.TaintTracking` for the full documentation.
12+
*/
13+
module TaintTracking2 {
14+
import semmle.code.cpp.ir.dataflow.internal.tainttracking2.TaintTrackingImpl
15+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
private import semmle.code.cpp.ir.IR
2+
private import semmle.code.cpp.ir.dataflow.DataFlow
3+
4+
/**
5+
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
6+
* (intra-procedural) step.
7+
*/
8+
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
9+
DataFlow::localFlowStep(nodeFrom, nodeTo)
10+
or
11+
localAdditionalTaintStep(nodeFrom, nodeTo)
12+
}
13+
14+
/**
15+
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
16+
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
17+
* different objects.
18+
*/
19+
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
20+
localInstructionTaintStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
21+
}
22+
23+
/**
24+
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
25+
* (intra-procedural) step.
26+
*/
27+
private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction nodeTo) {
28+
// Taint can flow through expressions that alter the value but preserve
29+
// more than one bit of it _or_ expressions that follow data through
30+
// pointer indirections.
31+
nodeTo.getAnOperand().getAnyDef() = nodeFrom and
32+
(
33+
nodeTo instanceof ArithmeticInstruction
34+
or
35+
nodeTo instanceof BitwiseInstruction
36+
or
37+
nodeTo instanceof PointerArithmeticInstruction
38+
or
39+
nodeTo instanceof FieldAddressInstruction
40+
or
41+
// The `CopyInstruction` case is also present in non-taint data flow, but
42+
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
43+
// from a definition of `myStruct` to a `myStruct.myField` expression.
44+
nodeTo instanceof CopyInstruction
45+
)
46+
or
47+
nodeTo.(LoadInstruction).getSourceAddress() = nodeFrom
48+
}
49+
50+
/**
51+
* Holds if taint may propagate from `source` to `sink` in zero or more local
52+
* (intra-procedural) steps.
53+
*/
54+
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
55+
56+
/**
57+
* Holds if taint can flow from `e1` to `e2` in zero or more
58+
* local (intra-procedural) steps.
59+
*/
60+
predicate localExprTaint(Expr e1, Expr e2) {
61+
localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2))
62+
}
63+
64+
/**
65+
* Holds if the additional step from `src` to `sink` should be included in all
66+
* global taint flow configurations.
67+
*/
68+
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
69+
localAdditionalTaintStep(src, sink)
70+
}
71+
72+
/**
73+
* Holds if `node` should be a barrier in all global taint flow configurations
74+
* but not in local taint.
75+
*/
76+
predicate defaultTaintBarrier(DataFlow::Node node) { none() }

0 commit comments

Comments
 (0)