Skip to content

Commit 1eccb8e

Browse files
committed
C++: Add a cache module to taint-tracking and ensure they happen in the same stage as the dataflow stage.
1 parent 6661132 commit 1eccb8e

File tree

2 files changed

+64
-52
lines changed

2 files changed

+64
-52
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ private module Cached {
124124
cached
125125
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
126126
(
127+
TaintTrackingUtil::forceCachingInSameStage() and
127128
// Def-use/Use-use flow
128129
SsaImpl::ssaFlow(nodeFrom, nodeTo)
129130
or

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,61 +9,72 @@ private import SsaImpl as Ssa
99
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
1010
private import semmle.code.cpp.ir.dataflow.FlowSteps
1111

12-
/**
13-
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
14-
* (intra-procedural) step. This relation is only used for local taint flow
15-
* (for example `TaintTracking::localTaint(source, sink)`) so it may contain
16-
* special cases that should only apply to local taint flow.
17-
*/
18-
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
19-
// dataflow step
20-
DataFlow::localFlowStep(nodeFrom, nodeTo)
21-
or
22-
// taint flow step
23-
localAdditionalTaintStep(nodeFrom, nodeTo, _)
24-
or
25-
// models-as-data summarized flow for local data flow (i.e. special case for flow
26-
// through calls to modeled functions, without relying on global dataflow to join
27-
// the dots).
28-
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
29-
}
30-
31-
/**
32-
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
33-
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
34-
* different objects.
35-
*/
3612
cached
37-
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
38-
operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and
39-
model = ""
40-
or
41-
modeledTaintStep(nodeFrom, nodeTo, model)
42-
or
43-
// Flow from (the indirection of) an operand of a pointer arithmetic instruction to the
44-
// indirection of the pointer arithmetic instruction. This provides flow from `source`
45-
// in `x[source]` to the result of the associated load instruction.
46-
exists(PointerArithmeticInstruction pai, int indirectionIndex |
47-
nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and
48-
hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1)
49-
) and
50-
model = ""
51-
or
52-
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and
53-
model = ""
54-
or
55-
// models-as-data summarized flow
56-
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
57-
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
58-
or
59-
// object->field conflation for content that is a `TaintInheritingContent`.
60-
exists(DataFlow::ContentSet f |
61-
readStep(nodeFrom, f, nodeTo) and
62-
f.getAReadContent() instanceof TaintInheritingContent
63-
) and
64-
model = ""
13+
private module Cached {
14+
private import DataFlowImplCommon as DataFlowImplCommon
15+
16+
cached
17+
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
18+
19+
/**
20+
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
21+
* (intra-procedural) step. This relation is only used for local taint flow
22+
* (for example `TaintTracking::localTaint(source, sink)`) so it may contain
23+
* special cases that should only apply to local taint flow.
24+
*/
25+
cached
26+
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
27+
// dataflow step
28+
DataFlow::localFlowStep(nodeFrom, nodeTo)
29+
or
30+
// taint flow step
31+
localAdditionalTaintStep(nodeFrom, nodeTo, _)
32+
or
33+
// models-as-data summarized flow for local data flow (i.e. special case for flow
34+
// through calls to modeled functions, without relying on global dataflow to join
35+
// the dots).
36+
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
37+
}
38+
39+
/**
40+
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
41+
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
42+
* different objects.
43+
*/
44+
cached
45+
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
46+
operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and
47+
model = ""
48+
or
49+
modeledTaintStep(nodeFrom, nodeTo, model)
50+
or
51+
// Flow from (the indirection of) an operand of a pointer arithmetic instruction to the
52+
// indirection of the pointer arithmetic instruction. This provides flow from `source`
53+
// in `x[source]` to the result of the associated load instruction.
54+
exists(PointerArithmeticInstruction pai, int indirectionIndex |
55+
nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and
56+
hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1)
57+
) and
58+
model = ""
59+
or
60+
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and
61+
model = ""
62+
or
63+
// models-as-data summarized flow
64+
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
65+
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
66+
or
67+
// object->field conflation for content that is a `TaintInheritingContent`.
68+
exists(DataFlow::ContentSet f |
69+
readStep(nodeFrom, f, nodeTo) and
70+
f.getAReadContent() instanceof TaintInheritingContent
71+
) and
72+
model = ""
73+
}
6574
}
6675

76+
import Cached
77+
6778
/**
6879
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
6980
* (intra-procedural) step.

0 commit comments

Comments
 (0)