Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7ccd48e

Browse files
committed
Make DefaultTaintTracking do operand->instruction->operand interleaving like DataFlowUtil.
1 parent ceaaac2 commit 7ccd48e

1 file changed

Lines changed: 37 additions & 49 deletions

File tree

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

Lines changed: 37 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,14 @@ private predicate nodeIsBarrierIn(DataFlow::Node node) {
204204

205205
cached
206206
private predicate commonTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
207-
instructionToInstructionTaintStep(fromNode.asInstruction(), toNode.asInstruction())
208-
or
209207
operandToInstructionTaintStep(fromNode.asOperand(), toNode.asInstruction())
210208
or
211-
operandToOperandTaintStep(fromNode.asOperand(), toNode.asOperand())
209+
instructionToOperandTaintStep(fromNode.asInstruction(), toNode.asOperand())
212210
}
213211

214-
private predicate operandToOperandTaintStep(Operand fromOperand, Operand toOperand) {
212+
private predicate instructionToOperandTaintStep(Instruction fromInstr, Operand toOperand) {
215213
exists(ReadSideEffectInstruction readInstr |
216-
fromOperand = readInstr.getArgumentOperand() and
214+
fromInstr = readInstr.getArgumentDef() and
217215
toOperand = readInstr.getSideEffectOperand()
218216
)
219217
}
@@ -256,18 +254,18 @@ private predicate operandToInstructionTaintStep(Operand fromOperand, Instruction
256254
outInstr.getPrimaryInstruction() = call
257255
)
258256
)
259-
}
260-
261-
private predicate instructionToInstructionTaintStep(Instruction i1, Instruction i2) {
257+
or
262258
// Flow through pointer dereference
263-
i2.(LoadInstruction).getSourceAddress() = i1
259+
toInstr.(LoadInstruction).getSourceAddressOperand() = fromOperand
264260
or
265261
// Flow through partial reads of arrays and unions
266-
i2.(LoadInstruction).getSourceValueOperand().getAnyDef() = i1 and
267-
not i1.isResultConflated() and
268-
(
269-
i1.getResultType() instanceof ArrayType or
270-
i1.getResultType() instanceof Union
262+
toInstr.(LoadInstruction).getSourceValueOperand() = fromOperand and
263+
exists(Instruction fromInstr | fromInstr = fromOperand.getAnyDef() |
264+
not fromInstr.isResultConflated() and
265+
(
266+
fromInstr.getResultType() instanceof ArrayType or
267+
fromInstr.getResultType() instanceof Union
268+
)
271269
)
272270
or
273271
// Unary instructions tend to preserve enough information in practice that we
@@ -277,63 +275,53 @@ private predicate instructionToInstructionTaintStep(Instruction i1, Instruction
277275
// `FieldAddressInstruction` could cause flow into one field to come out an
278276
// unrelated field. This would happen across function boundaries, where the IR
279277
// would not be able to match loads to stores.
280-
i2.(UnaryInstruction).getUnary() = i1 and
278+
toInstr.(UnaryInstruction).getUnaryOperand() = fromOperand and
281279
(
282-
not i2 instanceof FieldAddressInstruction
280+
not toInstr instanceof FieldAddressInstruction
283281
or
284-
i2.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
282+
toInstr.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union
285283
)
286284
or
287-
// Flow out of definition-by-reference
288-
i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and
289-
not i2.isResultConflated()
290-
or
291285
// Flow from an element to an array or union that contains it.
292-
i2.(ChiInstruction).getPartial() = i1 and
293-
not i2.isResultConflated() and
294-
exists(Type t | i2.getResultLanguageType().hasType(t, false) |
286+
toInstr.(ChiInstruction).getPartialOperand() = fromOperand and
287+
not toInstr.isResultConflated() and
288+
exists(Type t | toInstr.getResultLanguageType().hasType(t, false) |
295289
t instanceof Union
296290
or
297291
t instanceof ArrayType
298292
)
299293
or
300294
exists(BinaryInstruction bin |
301-
bin = i2 and
302-
predictableInstruction(i2.getAnOperand().getDef()) and
303-
i1 = i2.getAnOperand().getDef()
295+
bin = toInstr and
296+
predictableInstruction(toInstr.getAnOperand().getDef()) and
297+
fromOperand = toInstr.getAnOperand()
304298
)
305299
or
306300
// This is part of the translation of `a[i]`, where we want taint to flow
307301
// from `a`.
308-
i2.(PointerAddInstruction).getLeft() = i1
309-
or
310-
// Until we have from through indirections across calls, we'll take flow out
311-
// of the parameter and into its indirection.
312-
exists(IRFunction f, Parameter parameter |
313-
i1 = getInitializeParameter(f, parameter) and
314-
i2 = getInitializeIndirection(f, parameter)
315-
)
302+
toInstr.(PointerAddInstruction).getLeftOperand() = fromOperand
316303
or
317304
// Until we have flow through indirections across calls, we'll take flow out
318305
// of the indirection and into the argument.
319306
// When we get proper flow through indirections across calls, this code can be
320307
// moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class.
321308
exists(ReadSideEffectInstruction read |
322-
read.getAnOperand().(SideEffectOperand).getAnyDef() = i1 and
323-
read.getArgumentDef() = i2
309+
read.getSideEffectOperand() = fromOperand and
310+
read.getArgumentDef() = toInstr
324311
)
325-
}
326-
327-
pragma[noinline]
328-
private InitializeIndirectionInstruction getInitializeIndirection(IRFunction f, Parameter p) {
329-
result.getParameter() = p and
330-
result.getEnclosingIRFunction() = f
331-
}
332-
333-
pragma[noinline]
334-
private InitializeParameterInstruction getInitializeParameter(IRFunction f, Parameter p) {
335-
result.getParameter() = p and
336-
result.getEnclosingIRFunction() = f
312+
or
313+
// Until we have from through indirections across calls, we'll take flow out
314+
// of the parameter and into its indirection.
315+
// `InitializeIndirectionInstruction` only has a single operand: the address of the
316+
// value whose direction we are initializing. When initializing an indirection of a parameter `p`,
317+
// the IR looks like this:
318+
// ```
319+
// m1 = InitializeParameter[p] : &r1
320+
// r2 = Load[p] : r2, m1
321+
// m3 = InitializeIndirection[p] : &r2
322+
// ```
323+
// So by having flow from r2 to m3 we're enabling flow from `m1` to `m3`.
324+
toInstr.(InitializeIndirectionInstruction).getAnOperand() = fromOperand
337325
}
338326

339327
/**

0 commit comments

Comments
 (0)