Merge pull request #2797 from rdmarsh2/rdmarsh/cpp/malloc-alias-locations

C++: Support dynamic memory allocations in IR alias analysis
This commit is contained in:
Jonas Jensen
2020-03-02 08:49:59 +01:00
committed by GitHub
20 changed files with 394 additions and 10 deletions

View File

@@ -82,6 +82,7 @@ private newtype TOpcode =
TSizedBufferReadSideEffect() or
TSizedBufferMustWriteSideEffect() or
TSizedBufferMayWriteSideEffect() or
TInitializeDynamicAllocation() or
TChi() or
TInlineAsm() or
TUnreached() or
@@ -695,6 +696,11 @@ module Opcode {
final override string toString() { result = "SizedBufferMayWriteSideEffect" }
}
class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode,
TInitializeDynamicAllocation {
final override string toString() { result = "InitializeDynamicAllocation" }
}
class Chi extends Opcode, TChi {
final override string toString() { result = "Chi" }

View File

@@ -1350,6 +1350,26 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
/**
* Gets the address of the allocation this instruction is initializing.
*/
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
/**
* Gets the operand for the allocation this instruction is initializing.
*/
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/

View File

@@ -7,6 +7,9 @@ private newtype TAllocation =
TVariableAllocation(IRVariable var) or
TIndirectParameterAllocation(IRAutomaticUserVariable var) {
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)
} or
TDynamicAllocation(CallInstruction call) {
exists(InitializeDynamicAllocationInstruction instr | instr.getPrimaryInstruction() = call)
}
/**
@@ -95,3 +98,29 @@ class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocati
final override predicate alwaysEscapes() { none() }
}
class DynamicAllocation extends Allocation, TDynamicAllocation {
CallInstruction call;
DynamicAllocation() { this = TDynamicAllocation(call) }
final override string toString() {
result = call.toString() + " at " + call.getLocation() // This isn't performant, but it's only used in test/dump code right now.
}
final override CallInstruction getABaseInstruction() { result = call }
final override IRFunction getEnclosingIRFunction() { result = call.getEnclosingIRFunction() }
final override Language::Location getLocation() { result = call.getLocation() }
final override string getUniqueId() { result = call.getUniqueId() }
final override IRType getIRType() { result instanceof IRUnknownType }
final override predicate isReadOnly() { none() }
final override predicate isAlwaysAllocatedOnStack() { none() }
final override predicate alwaysEscapes() { none() }
}

View File

@@ -68,8 +68,12 @@ private newtype TMemoryLocation =
) and
languageType = type.getCanonicalLanguageType()
} or
TEntireAllocationMemoryLocation(IndirectParameterAllocation var, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
TEntireAllocationMemoryLocation(Allocation var, boolean isMayAccess) {
(
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
) and
(isMayAccess = false or isMayAccess = true)
} or
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true

View File

@@ -1350,6 +1350,26 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
/**
* Gets the address of the allocation this instruction is initializing.
*/
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
/**
* Gets the operand for the allocation this instruction is initializing.
*/
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/

View File

@@ -341,16 +341,32 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects {
)
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) { none() }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
expr.getTarget() instanceof AllocationFunction and
opcode instanceof Opcode::InitializeDynamicAllocation and
tag = OnlyInstructionTag() and
type = getUnknownType()
}
override Instruction getFirstInstruction() { result = getChild(0).getFirstInstruction() }
override Instruction getFirstInstruction() {
if expr.getTarget() instanceof AllocationFunction
then result = getInstruction(OnlyInstructionTag())
else result = getChild(0).getFirstInstruction()
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = OnlyInstructionTag() and
kind = gotoEdge() and
expr.getTarget() instanceof AllocationFunction and
if exists(getChild(0))
then result = getChild(0).getFirstInstruction()
else result = getParent().getChildSuccessor(this)
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { none() }
override CppType getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) {
none()
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
tag = OnlyInstructionTag() and
operandTag = addressOperand() and
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
}
override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {

View File

@@ -411,7 +411,9 @@ newtype TTranslatedElement =
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
// The side effects of a `Call`
TTranslatedSideEffects(Call expr) {
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall
exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or
expr instanceof ConstructorCall or
expr.getTarget() instanceof AllocationFunction
} or // A precise side effect of an argument to a `Call`
TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) {
(

View File

@@ -1350,6 +1350,26 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
}
/**
* An instruction representing the initial value of newly allocated memory, e.g. the result of a
* call to `malloc`.
*/
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
InitializeDynamicAllocationInstruction() {
getOpcode() instanceof Opcode::InitializeDynamicAllocation
}
/**
* Gets the address of the allocation this instruction is initializing.
*/
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
/**
* Gets the operand for the allocation this instruction is initializing.
*/
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
}
/**
* An instruction representing a GNU or MSVC inline assembly statement.
*/