mirror of
https://github.com/github/codeql.git
synced 2026-05-03 12:45:27 +02:00
C++: Dynamic allocations in IR alias analysis
This commit is contained in:
@@ -82,6 +82,7 @@ private newtype TOpcode =
|
||||
TSizedBufferReadSideEffect() or
|
||||
TSizedBufferMustWriteSideEffect() or
|
||||
TSizedBufferMayWriteSideEffect() or
|
||||
TInitializeDynamicAllocation() or
|
||||
TChi() or
|
||||
TInlineAsm() or
|
||||
TUnreached() or
|
||||
@@ -695,6 +696,10 @@ 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" }
|
||||
|
||||
|
||||
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
InitializeDynamicAllocationInstruction() {
|
||||
getOpcode() instanceof Opcode::InitializeDynamicAllocation
|
||||
}
|
||||
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a GNU or MSVC inline assembly statement.
|
||||
*/
|
||||
|
||||
@@ -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,31 @@ 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() // TODO: make this both short and unique
|
||||
}
|
||||
|
||||
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 // TODO: look at casts and sizes?
|
||||
}
|
||||
|
||||
final override predicate isReadOnly() { none() }
|
||||
|
||||
final override predicate isAlwaysAllocatedOnStack() { none() }
|
||||
|
||||
final override predicate alwaysEscapes() { none() }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
InitializeDynamicAllocationInstruction() {
|
||||
getOpcode() instanceof Opcode::InitializeDynamicAllocation
|
||||
}
|
||||
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a GNU or MSVC inline assembly statement.
|
||||
*/
|
||||
|
||||
@@ -341,16 +341,31 @@ 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() // TODO: precise type
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
|
||||
@@ -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) {
|
||||
(
|
||||
|
||||
@@ -1340,6 +1340,20 @@ class SizedBufferMayWriteSideEffectInstruction extends WriteSideEffectInstructio
|
||||
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
InitializeDynamicAllocationInstruction() {
|
||||
getOpcode() instanceof Opcode::InitializeDynamicAllocation
|
||||
}
|
||||
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a GNU or MSVC inline assembly statement.
|
||||
*/
|
||||
|
||||
@@ -8,12 +8,6 @@
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | AST only |
|
||||
| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:85:8:85:11 | copy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:9:86:12 | copy | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | AST only |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | AST only |
|
||||
|
||||
@@ -40,9 +40,15 @@
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | |
|
||||
| test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:11:36:11:37 | s2 | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:17:83:24 | userName | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:33 | call to getenv | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:83:28:83:46 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:2:86:7 | call to strcpy | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:86:15:86:22 | userName | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:6:88:27 | ! ... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:12 | call to strcmp | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:7:88:27 | (bool)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | (const char *)... | |
|
||||
| test.cpp:83:28:83:33 | call to getenv | test.cpp:88:14:88:17 | copy | |
|
||||
|
||||
@@ -1261,21 +1261,22 @@ ssa.cpp:
|
||||
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
|
||||
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_9
|
||||
# 269| m269_7(unknown) = Chi : total:m268_9, partial:m269_6
|
||||
# 269| m269_8(void *) = Store : &:r269_1, r269_5
|
||||
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
|
||||
# 269| m269_9(void *) = Store : &:r269_1, r269_5
|
||||
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
|
||||
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_8
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_9
|
||||
# 270| r270_4(glval<void *>) = VariableAddress[s] :
|
||||
# 270| r270_5(void *) = Load : &:r270_4, m268_7
|
||||
# 270| r270_6(glval<int>) = VariableAddress[size] :
|
||||
# 270| r270_7(int) = Load : &:r270_6, m268_11
|
||||
# 270| r270_8(void *) = Call : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
|
||||
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7
|
||||
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_8
|
||||
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
|
||||
# 270| m270_11(unknown) = Chi : total:m269_7, partial:m270_10
|
||||
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
|
||||
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
|
||||
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_8
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_9
|
||||
# 271| m271_4(void *) = Store : &:r271_1, r271_3
|
||||
# 268| v268_12(void) = ReturnIndirection : &:r268_8, ~m270_11
|
||||
# 268| r268_13(glval<void *>) = VariableAddress[#return] :
|
||||
|
||||
@@ -1256,10 +1256,11 @@ ssa.cpp:
|
||||
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
|
||||
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_4
|
||||
# 269| m269_7(unknown) = Chi : total:m268_4, partial:m269_6
|
||||
# 269| m269_8(void *) = Store : &:r269_1, r269_5
|
||||
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
|
||||
# 269| m269_9(void *) = Store : &:r269_1, r269_5
|
||||
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
|
||||
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_8
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_9
|
||||
# 270| r270_4(glval<void *>) = VariableAddress[s] :
|
||||
# 270| r270_5(void *) = Load : &:r270_4, m268_7
|
||||
# 270| r270_6(glval<int>) = VariableAddress[size] :
|
||||
@@ -1267,14 +1268,14 @@ ssa.cpp:
|
||||
# 270| r270_8(void *) = Call : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
|
||||
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m268_9
|
||||
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
|
||||
# 270| m270_11(unknown) = Chi : total:m269_7, partial:m270_10
|
||||
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
|
||||
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
|
||||
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_8
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_9
|
||||
# 271| m271_4(void *) = Store : &:r271_1, r271_3
|
||||
# 268| v268_12(void) = ReturnIndirection : &:r268_8, m268_9
|
||||
# 268| r268_13(glval<void *>) = VariableAddress[#return] :
|
||||
# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4
|
||||
# 268| v268_15(void) = UnmodeledUse : mu*
|
||||
# 268| v268_16(void) = AliasedUse : ~m270_11
|
||||
# 268| v268_16(void) = AliasedUse : ~m269_7
|
||||
# 268| v268_17(void) = ExitFunction :
|
||||
|
||||
@@ -1168,10 +1168,11 @@ ssa.cpp:
|
||||
# 269| r269_4(int) = Load : &:r269_3, m268_10
|
||||
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
|
||||
# 269| mu269_6(unknown) = ^CallSideEffect : ~mu268_4
|
||||
# 269| m269_7(void *) = Store : &:r269_1, r269_5
|
||||
# 269| mu269_7(unknown) = ^InitializeDynamicAllocation : &:r269_5
|
||||
# 269| m269_8(void *) = Store : &:r269_1, r269_5
|
||||
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
|
||||
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_7
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_8
|
||||
# 270| r270_4(glval<void *>) = VariableAddress[s] :
|
||||
# 270| r270_5(void *) = Load : &:r270_4, m268_6
|
||||
# 270| r270_6(glval<int>) = VariableAddress[size] :
|
||||
@@ -1181,7 +1182,7 @@ ssa.cpp:
|
||||
# 270| mu270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
|
||||
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
|
||||
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_7
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_8
|
||||
# 271| m271_4(void *) = Store : &:r271_1, r271_3
|
||||
# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4
|
||||
# 268| r268_12(glval<void *>) = VariableAddress[#return] :
|
||||
|
||||
@@ -1168,10 +1168,11 @@ ssa.cpp:
|
||||
# 269| r269_4(int) = Load : &:r269_3, m268_10
|
||||
# 269| r269_5(void *) = Call : func:r269_2, 0:r269_4
|
||||
# 269| mu269_6(unknown) = ^CallSideEffect : ~mu268_4
|
||||
# 269| m269_7(void *) = Store : &:r269_1, r269_5
|
||||
# 269| mu269_7(unknown) = ^InitializeDynamicAllocation : &:r269_5
|
||||
# 269| m269_8(void *) = Store : &:r269_1, r269_5
|
||||
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
|
||||
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_7
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_8
|
||||
# 270| r270_4(glval<void *>) = VariableAddress[s] :
|
||||
# 270| r270_5(void *) = Load : &:r270_4, m268_6
|
||||
# 270| r270_6(glval<int>) = VariableAddress[size] :
|
||||
@@ -1181,7 +1182,7 @@ ssa.cpp:
|
||||
# 270| mu270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
|
||||
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
|
||||
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_7
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_8
|
||||
# 271| m271_4(void *) = Store : &:r271_1, r271_3
|
||||
# 268| v268_11(void) = ReturnIndirection : &:r268_7, ~mu268_4
|
||||
# 268| r268_12(glval<void *>) = VariableAddress[#return] :
|
||||
|
||||
Reference in New Issue
Block a user