Skip to content

Commit 7879dde

Browse files
author
Dave Bartolomeo
authored
Merge pull request github#3097 from jbj/detect-conflated-memory
C++: Implement Instruction.isResultConflated
2 parents 0f70da2 + 2b2667a commit 7879dde

38 files changed

+630
-74
lines changed

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
183183
i2.(UnaryInstruction).getUnary() = i1
184184
or
185185
i2.(ChiInstruction).getPartial() = i1 and
186-
not isChiForAllAliasedMemory(i2)
186+
not i2.isResultConflated()
187187
or
188188
exists(BinaryInstruction bin |
189189
bin = i2 and
@@ -276,19 +276,6 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
276276
)
277277
}
278278

279-
/**
280-
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
281-
* Taint should not pass through these instructions since they tend to mix up
282-
* unrelated objects.
283-
*/
284-
private predicate isChiForAllAliasedMemory(Instruction instr) {
285-
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
286-
or
287-
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
288-
or
289-
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
290-
}
291-
292279
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
293280
// Taint flow from parameter to return value
294281
exists(FunctionInput modelIn, FunctionOutput modelOut |

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,36 @@ module InstructionSanity {
274274
funcText = Language::getIdentityString(func.getFunction())
275275
}
276276

277+
/**
278+
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
279+
* memory.
280+
*/
281+
private predicate isOnAliasedDefinitionChain(Instruction instr) {
282+
instr instanceof AliasedDefinitionInstruction
283+
or
284+
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
285+
or
286+
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
287+
}
288+
289+
private predicate shouldBeConflated(Instruction instr) {
290+
isOnAliasedDefinitionChain(instr)
291+
or
292+
instr instanceof UnmodeledDefinitionInstruction
293+
or
294+
instr.getOpcode() instanceof Opcode::InitializeNonLocal
295+
}
296+
297+
query predicate notMarkedAsConflated(Instruction instr) {
298+
shouldBeConflated(instr) and
299+
not instr.isResultConflated()
300+
}
301+
302+
query predicate wronglyMarkedAsConflated(Instruction instr) {
303+
instr.isResultConflated() and
304+
not shouldBeConflated(instr)
305+
}
306+
277307
query predicate invalidOverlap(
278308
MemoryOperand useOperand, string message, IRFunction func, string funcText
279309
) {

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
338338
Construction::hasModeledMemoryResult(this)
339339
}
340340

341+
/**
342+
* Holds if this is an instruction with a memory result that represents a
343+
* conflation of more than one memory allocation.
344+
*
345+
* This happens in practice when dereferencing a pointer that cannot be
346+
* tracked back to a single local allocation. Such memory is instead modeled
347+
* as originating on the `AliasedDefinitionInstruction` at the entry of the
348+
* function.
349+
*/
350+
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
351+
341352
/**
342353
* Gets the successor of this instruction along the control flow edge
343354
* specified by `kind`.

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
354354
final override predicate isMayAccess() { isMayAccess = true }
355355
}
356356

357+
/** A virtual variable that groups all escaped memory within a function. */
357358
class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
358359
AliasedVirtualVariable() { not isMayAccess() }
359360
}
@@ -429,10 +430,18 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
429430
use instanceof EntireAllocationMemoryLocation and
430431
result instanceof MustExactlyOverlap
431432
or
432-
// EntireAllocationMemoryLocation totally overlaps any ___location within the same virtual
433-
// variable.
434433
not use instanceof EntireAllocationMemoryLocation and
435-
result instanceof MustTotallyOverlap
434+
if def.getAllocation() = use.getAllocation()
435+
then
436+
// EntireAllocationMemoryLocation totally overlaps any ___location within
437+
// the same allocation.
438+
result instanceof MustTotallyOverlap
439+
else (
440+
// There is no overlap with a ___location that's known to belong to a
441+
// different allocation, but all other locations may partially overlap.
442+
not exists(use.getAllocation()) and
443+
result instanceof MayPartiallyOverlap
444+
)
436445
)
437446
or
438447
exists(VariableMemoryLocation defVariableLocation |

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ private module Cached {
6565
instruction instanceof ChiInstruction // Chis always have modeled results
6666
}
6767

68+
cached
69+
predicate hasConflatedMemoryResult(Instruction instruction) {
70+
instruction instanceof UnmodeledDefinitionInstruction
71+
or
72+
instruction instanceof AliasedDefinitionInstruction
73+
or
74+
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
75+
or
76+
// Chi instructions track virtual variables, and therefore a chi instruction is
77+
// conflated if it's associated with the aliased virtual variable.
78+
exists(OldInstruction oldInstruction | instruction = Chi(oldInstruction) |
79+
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
80+
Alias::AliasedVirtualVariable
81+
)
82+
or
83+
// Phi instructions track locations, and therefore a phi instruction is
84+
// conflated if it's associated with a conflated ___location.
85+
exists(Alias::MemoryLocation ___location |
86+
instruction = Phi(_, ___location) and
87+
not exists(___location.getAllocation())
88+
)
89+
}
90+
6891
cached
6992
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
7093
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,36 @@ module InstructionSanity {
274274
funcText = Language::getIdentityString(func.getFunction())
275275
}
276276

277+
/**
278+
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
279+
* memory.
280+
*/
281+
private predicate isOnAliasedDefinitionChain(Instruction instr) {
282+
instr instanceof AliasedDefinitionInstruction
283+
or
284+
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
285+
or
286+
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
287+
}
288+
289+
private predicate shouldBeConflated(Instruction instr) {
290+
isOnAliasedDefinitionChain(instr)
291+
or
292+
instr instanceof UnmodeledDefinitionInstruction
293+
or
294+
instr.getOpcode() instanceof Opcode::InitializeNonLocal
295+
}
296+
297+
query predicate notMarkedAsConflated(Instruction instr) {
298+
shouldBeConflated(instr) and
299+
not instr.isResultConflated()
300+
}
301+
302+
query predicate wronglyMarkedAsConflated(Instruction instr) {
303+
instr.isResultConflated() and
304+
not shouldBeConflated(instr)
305+
}
306+
277307
query predicate invalidOverlap(
278308
MemoryOperand useOperand, string message, IRFunction func, string funcText
279309
) {

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
338338
Construction::hasModeledMemoryResult(this)
339339
}
340340

341+
/**
342+
* Holds if this is an instruction with a memory result that represents a
343+
* conflation of more than one memory allocation.
344+
*
345+
* This happens in practice when dereferencing a pointer that cannot be
346+
* tracked back to a single local allocation. Such memory is instead modeled
347+
* as originating on the `AliasedDefinitionInstruction` at the entry of the
348+
* function.
349+
*/
350+
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
351+
341352
/**
342353
* Gets the successor of this instruction along the control flow edge
343354
* specified by `kind`.

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ private module Cached {
6161
cached
6262
predicate hasModeledMemoryResult(Instruction instruction) { none() }
6363

64+
cached
65+
predicate hasConflatedMemoryResult(Instruction instruction) {
66+
instruction instanceof UnmodeledDefinitionInstruction
67+
or
68+
instruction instanceof AliasedDefinitionInstruction
69+
or
70+
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
71+
}
72+
6473
cached
6574
Expr getInstructionConvertedResultExpression(Instruction instruction) {
6675
exists(TranslatedExpr translatedExpr |

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,36 @@ module InstructionSanity {
274274
funcText = Language::getIdentityString(func.getFunction())
275275
}
276276

277+
/**
278+
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
279+
* memory.
280+
*/
281+
private predicate isOnAliasedDefinitionChain(Instruction instr) {
282+
instr instanceof AliasedDefinitionInstruction
283+
or
284+
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
285+
or
286+
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
287+
}
288+
289+
private predicate shouldBeConflated(Instruction instr) {
290+
isOnAliasedDefinitionChain(instr)
291+
or
292+
instr instanceof UnmodeledDefinitionInstruction
293+
or
294+
instr.getOpcode() instanceof Opcode::InitializeNonLocal
295+
}
296+
297+
query predicate notMarkedAsConflated(Instruction instr) {
298+
shouldBeConflated(instr) and
299+
not instr.isResultConflated()
300+
}
301+
302+
query predicate wronglyMarkedAsConflated(Instruction instr) {
303+
instr.isResultConflated() and
304+
not shouldBeConflated(instr)
305+
}
306+
277307
query predicate invalidOverlap(
278308
MemoryOperand useOperand, string message, IRFunction func, string funcText
279309
) {

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
338338
Construction::hasModeledMemoryResult(this)
339339
}
340340

341+
/**
342+
* Holds if this is an instruction with a memory result that represents a
343+
* conflation of more than one memory allocation.
344+
*
345+
* This happens in practice when dereferencing a pointer that cannot be
346+
* tracked back to a single local allocation. Such memory is instead modeled
347+
* as originating on the `AliasedDefinitionInstruction` at the entry of the
348+
* function.
349+
*/
350+
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
351+
341352
/**
342353
* Gets the successor of this instruction along the control flow edge
343354
* specified by `kind`.

0 commit comments

Comments
 (0)