Skip to content

Commit 7b860d9

Browse files
committed
Change TaintTracking to DataFlow
1 parent 5ea652b commit 7b860d9

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

cpp/misra/src/rules/RULE-8-7-1/PointerArithmeticFormsAnInvalidPointer.ql

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ import cpp
1616
import codingstandards.cpp.misra
1717
import semmle.code.cpp.dataflow.new.TaintTracking
1818
import semmle.code.cpp.security.BufferAccess
19+
private import semmle.code.cpp.ir.IR // For PointerArithmeticInstruction (see TrackArray::isAdditionalFlowStep/2 below)
20+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate // For PointerArithmeticInstruction (see TrackArray::isAdditionalFlowStep/2 below)
21+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil // For PointerArithmeticInstruction (see TrackArray::isAdditionalFlowStep/2 below)
22+
private import semmle.code.cpp.ir.dataflow.FlowSteps // For PointerArithmeticInstruction (see TrackArray::isAdditionalFlowStep/2 below)
23+
private import semmle.code.cpp.ir.dataflow.internal.SsaInternals as Ssa
1924

2025
class ArrayDeclaration extends VariableDeclarationEntry {
2126
int length;
@@ -147,6 +152,50 @@ class PointerFormation extends TPointerFormation {
147152
}
148153
}
149154

155+
/**
156+
* NOTE
157+
*/
158+
private predicate operandToInstructionTaintStep(Operand opFrom, Instruction instrTo) {
159+
// Taint can flow through expressions that alter the value but preserve
160+
// more than one bit of it _or_ expressions that follow data through
161+
// pointer indirections.
162+
instrTo.getAnOperand() = opFrom and
163+
(
164+
instrTo instanceof ArithmeticInstruction
165+
or
166+
instrTo instanceof BitwiseInstruction
167+
or
168+
instrTo instanceof PointerArithmeticInstruction
169+
)
170+
or
171+
// Taint flow from an address to its dereference.
172+
Ssa::isDereference(instrTo, opFrom, _)
173+
or
174+
// Unary instructions tend to preserve enough information in practice that we
175+
// want taint to flow through.
176+
// The exception is `FieldAddressInstruction`. Together with the rules below for
177+
// `LoadInstruction`s and `ChiInstruction`s, flow through `FieldAddressInstruction`
178+
// could cause flow into one field to come out an unrelated field.
179+
// This would happen across function boundaries, where the IR would not be able to
180+
// match loads to stores.
181+
instrTo.(UnaryInstruction).getUnaryOperand() = opFrom and
182+
(
183+
not instrTo instanceof FieldAddressInstruction
184+
or
185+
instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
186+
)
187+
or
188+
// Taint from int to boolean casts. This ensures that we have flow to `!x` in:
189+
// ```cpp
190+
// x = integer_source();
191+
// if(!x) { ... }
192+
// ```
193+
exists(Operand zero |
194+
zero.getDef().(ConstantValueInstruction).getValue() = "0" and
195+
instrTo.(CompareNEInstruction).hasOperands(opFrom, zero)
196+
)
197+
}
198+
150199
module TrackArrayConfig implements DataFlow::ConfigSig {
151200
predicate isSource(DataFlow::Node node) {
152201
exists(ArrayAllocation arrayAllocation | node = arrayAllocation.getNode())
@@ -155,9 +204,22 @@ module TrackArrayConfig implements DataFlow::ConfigSig {
155204
predicate isSink(DataFlow::Node node) {
156205
exists(PointerFormation pointerFormation | node = pointerFormation.getNode())
157206
}
207+
208+
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
209+
/*
210+
* NOTE
211+
*/
212+
213+
operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction())
214+
or
215+
exists(PointerArithmeticInstruction pai, int indirectionIndex |
216+
nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and
217+
hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1)
218+
)
219+
}
158220
}
159221

160-
module TrackArray = TaintTracking::Global<TrackArrayConfig>;
222+
module TrackArray = DataFlow::Global<TrackArrayConfig>;
161223

162224
private predicate arrayIndexExceedsOutOfBounds(
163225
DataFlow::Node arrayDeclarationNode, DataFlow::Node pointerFormationNode

0 commit comments

Comments
 (0)