Skip to content

Commit bb53780

Browse files
committed
C++: Add flow through unary instructions and pointer/indirection conflation for parameters. These rules are copy/pasted from DefaultTaintTracking. The conflation rules will hopefully be removed as part of #5089.
1 parent 23876cb commit bb53780

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,26 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst
6464
or
6565
instrTo instanceof PointerArithmeticInstruction
6666
or
67-
instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
68-
or
6967
// The `CopyInstruction` case is also present in non-taint data flow, but
7068
// that uses `getDef` rather than `getAnyDef`. For taint, we want flow
7169
// from a definition of `myStruct` to a `myStruct.myField` expression.
7270
instrTo instanceof CopyInstruction
7371
)
7472
or
73+
// Unary instructions tend to preserve enough information in practice that we
74+
// want taint to flow through.
75+
// The exception is `FieldAddressInstruction`. Together with the rules below for
76+
// `LoadInstruction`s and `ChiInstruction`s, flow through `FieldAddressInstruction`
77+
// could cause flow into one field to come out an unrelated field.
78+
// This would happen across function boundaries, where the IR would not be able to
79+
// match loads to stores.
80+
instrTo.(UnaryInstruction).getUnaryOperand() = opFrom and
81+
(
82+
not instrTo instanceof FieldAddressInstruction
83+
or
84+
instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
85+
)
86+
or
7587
instrTo.(LoadInstruction).getSourceAddressOperand() = opFrom
7688
or
7789
// Flow from an element to an array or union that contains it.
@@ -83,6 +95,29 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst
8395
t instanceof ArrayType
8496
)
8597
or
98+
// Until we have flow through indirections across calls, we'll take flow out
99+
// of the indirection and into the argument.
100+
// When we get proper flow through indirections across calls, this code can be
101+
// moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class.
102+
exists(ReadSideEffectInstruction read |
103+
read.getSideEffectOperand() = opFrom and
104+
read.getArgumentDef() = instrTo
105+
)
106+
or
107+
// Until we have from through indirections across calls, we'll take flow out
108+
// of the parameter and into its indirection.
109+
// `InitializeIndirectionInstruction` only has a single operand: the address of the
110+
// value whose indirection we are initializing. When initializing an indirection of a parameter `p`,
111+
// the IR looks like this:
112+
// ```
113+
// m1 = InitializeParameter[p] : &r1
114+
// r2 = Load[p] : r2, m1
115+
// m3 = InitializeIndirection[p] : &r2
116+
// ```
117+
// So by having flow from `r2` to `m3` we're enabling flow from `m1` to `m3`. This relies on the
118+
// `LoadOperand`'s overlap being exact.
119+
instrTo.(InitializeIndirectionInstruction).getAnOperand() = opFrom
120+
or
86121
modeledTaintStep(opFrom, instrTo)
87122
}
88123

0 commit comments

Comments
 (0)