mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge branch 'master' into ir-flow-fields
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
- [ncp](https://www.npmjs.com/package/ncp)
|
||||
- [node-dir](https://www.npmjs.com/package/node-dir)
|
||||
- [path-exists](https://www.npmjs.com/package/path-exists)
|
||||
- [pg](https://www.npmjs.com/package/pg)
|
||||
- [react](https://www.npmjs.com/package/react)
|
||||
- [recursive-readdir](https://www.npmjs.com/package/recursive-readdir)
|
||||
- [request](https://www.npmjs.com/package/request)
|
||||
|
||||
@@ -60,7 +60,14 @@ private DataFlow::Node getNodeForSource(Expr source) {
|
||||
(
|
||||
result = DataFlow::exprNode(source)
|
||||
or
|
||||
result = DataFlow::definitionByReferenceNode(source)
|
||||
// Some of the sources in `isUserInput` are intended to match the value of
|
||||
// an expression, while others (those modeled below) are intended to match
|
||||
// the taint that propagates out of an argument, like the `char *` argument
|
||||
// to `gets`. It's impossible here to tell which is which, but the "access
|
||||
// to argv" source is definitely not intended to match an output argument,
|
||||
// and it causes false positives if we let it.
|
||||
result = DataFlow::definitionByReferenceNode(source) and
|
||||
not argv(source.(VariableAccess).getTarget())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -183,7 +190,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
|
||||
i2.(UnaryInstruction).getUnary() = i1
|
||||
or
|
||||
i2.(ChiInstruction).getPartial() = i1 and
|
||||
not isChiForAllAliasedMemory(i2)
|
||||
not i2.isResultConflated()
|
||||
or
|
||||
exists(BinaryInstruction bin |
|
||||
bin = i2 and
|
||||
@@ -276,19 +283,6 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
|
||||
* Taint should not pass through these instructions since they tend to mix up
|
||||
* unrelated objects.
|
||||
*/
|
||||
private predicate isChiForAllAliasedMemory(Instruction instr) {
|
||||
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
|
||||
// Taint flow from parameter to return value
|
||||
exists(FunctionInput modelIn, FunctionOutput modelOut |
|
||||
|
||||
@@ -274,6 +274,36 @@ module InstructionSanity {
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
|
||||
* memory.
|
||||
*/
|
||||
private predicate isOnAliasedDefinitionChain(Instruction instr) {
|
||||
instr instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate shouldBeConflated(Instruction instr) {
|
||||
isOnAliasedDefinitionChain(instr)
|
||||
or
|
||||
instr instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instr.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
query predicate notMarkedAsConflated(Instruction instr) {
|
||||
shouldBeConflated(instr) and
|
||||
not instr.isResultConflated()
|
||||
}
|
||||
|
||||
query predicate wronglyMarkedAsConflated(Instruction instr) {
|
||||
instr.isResultConflated() and
|
||||
not shouldBeConflated(instr)
|
||||
}
|
||||
|
||||
query predicate invalidOverlap(
|
||||
MemoryOperand useOperand, string message, IRFunction func, string funcText
|
||||
) {
|
||||
|
||||
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is an instruction with a memory result that represents a
|
||||
* conflation of more than one memory allocation.
|
||||
*
|
||||
* This happens in practice when dereferencing a pointer that cannot be
|
||||
* tracked back to a single local allocation. Such memory is instead modeled
|
||||
* as originating on the `AliasedDefinitionInstruction` at the entry of the
|
||||
* function.
|
||||
*/
|
||||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
|
||||
|
||||
/**
|
||||
* Gets the successor of this instruction along the control flow edge
|
||||
* specified by `kind`.
|
||||
|
||||
@@ -354,6 +354,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
||||
final override predicate isMayAccess() { isMayAccess = true }
|
||||
}
|
||||
|
||||
/** A virtual variable that groups all escaped memory within a function. */
|
||||
class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
|
||||
AliasedVirtualVariable() { not isMayAccess() }
|
||||
}
|
||||
@@ -429,10 +430,18 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
use instanceof EntireAllocationMemoryLocation and
|
||||
result instanceof MustExactlyOverlap
|
||||
or
|
||||
// EntireAllocationMemoryLocation totally overlaps any location within the same virtual
|
||||
// variable.
|
||||
not use instanceof EntireAllocationMemoryLocation and
|
||||
result instanceof MustTotallyOverlap
|
||||
if def.getAllocation() = use.getAllocation()
|
||||
then
|
||||
// EntireAllocationMemoryLocation totally overlaps any location within
|
||||
// the same allocation.
|
||||
result instanceof MustTotallyOverlap
|
||||
else (
|
||||
// There is no overlap with a location that's known to belong to a
|
||||
// different allocation, but all other locations may partially overlap.
|
||||
not exists(use.getAllocation()) and
|
||||
result instanceof MayPartiallyOverlap
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(VariableMemoryLocation defVariableLocation |
|
||||
|
||||
@@ -65,6 +65,29 @@ private module Cached {
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasConflatedMemoryResult(Instruction instruction) {
|
||||
instruction instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instruction instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
or
|
||||
// Chi instructions track virtual variables, and therefore a chi instruction is
|
||||
// conflated if it's associated with the aliased virtual variable.
|
||||
exists(OldInstruction oldInstruction | instruction = Chi(oldInstruction) |
|
||||
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
|
||||
Alias::AliasedVirtualVariable
|
||||
)
|
||||
or
|
||||
// Phi instructions track locations, and therefore a phi instruction is
|
||||
// conflated if it's associated with a conflated location.
|
||||
exists(Alias::MemoryLocation location |
|
||||
instruction = Phi(_, location) and
|
||||
not exists(location.getAllocation())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
|
||||
@@ -274,6 +274,36 @@ module InstructionSanity {
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
|
||||
* memory.
|
||||
*/
|
||||
private predicate isOnAliasedDefinitionChain(Instruction instr) {
|
||||
instr instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate shouldBeConflated(Instruction instr) {
|
||||
isOnAliasedDefinitionChain(instr)
|
||||
or
|
||||
instr instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instr.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
query predicate notMarkedAsConflated(Instruction instr) {
|
||||
shouldBeConflated(instr) and
|
||||
not instr.isResultConflated()
|
||||
}
|
||||
|
||||
query predicate wronglyMarkedAsConflated(Instruction instr) {
|
||||
instr.isResultConflated() and
|
||||
not shouldBeConflated(instr)
|
||||
}
|
||||
|
||||
query predicate invalidOverlap(
|
||||
MemoryOperand useOperand, string message, IRFunction func, string funcText
|
||||
) {
|
||||
|
||||
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is an instruction with a memory result that represents a
|
||||
* conflation of more than one memory allocation.
|
||||
*
|
||||
* This happens in practice when dereferencing a pointer that cannot be
|
||||
* tracked back to a single local allocation. Such memory is instead modeled
|
||||
* as originating on the `AliasedDefinitionInstruction` at the entry of the
|
||||
* function.
|
||||
*/
|
||||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
|
||||
|
||||
/**
|
||||
* Gets the successor of this instruction along the control flow edge
|
||||
* specified by `kind`.
|
||||
|
||||
@@ -61,6 +61,15 @@ private module Cached {
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
cached
|
||||
predicate hasConflatedMemoryResult(Instruction instruction) {
|
||||
instruction instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instruction instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
exists(TranslatedExpr translatedExpr |
|
||||
|
||||
@@ -274,6 +274,36 @@ module InstructionSanity {
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
|
||||
* memory.
|
||||
*/
|
||||
private predicate isOnAliasedDefinitionChain(Instruction instr) {
|
||||
instr instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate shouldBeConflated(Instruction instr) {
|
||||
isOnAliasedDefinitionChain(instr)
|
||||
or
|
||||
instr instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instr.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
query predicate notMarkedAsConflated(Instruction instr) {
|
||||
shouldBeConflated(instr) and
|
||||
not instr.isResultConflated()
|
||||
}
|
||||
|
||||
query predicate wronglyMarkedAsConflated(Instruction instr) {
|
||||
instr.isResultConflated() and
|
||||
not shouldBeConflated(instr)
|
||||
}
|
||||
|
||||
query predicate invalidOverlap(
|
||||
MemoryOperand useOperand, string message, IRFunction func, string funcText
|
||||
) {
|
||||
|
||||
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is an instruction with a memory result that represents a
|
||||
* conflation of more than one memory allocation.
|
||||
*
|
||||
* This happens in practice when dereferencing a pointer that cannot be
|
||||
* tracked back to a single local allocation. Such memory is instead modeled
|
||||
* as originating on the `AliasedDefinitionInstruction` at the entry of the
|
||||
* function.
|
||||
*/
|
||||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
|
||||
|
||||
/**
|
||||
* Gets the successor of this instruction along the control flow edge
|
||||
* specified by `kind`.
|
||||
|
||||
@@ -65,6 +65,29 @@ private module Cached {
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasConflatedMemoryResult(Instruction instruction) {
|
||||
instruction instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instruction instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
or
|
||||
// Chi instructions track virtual variables, and therefore a chi instruction is
|
||||
// conflated if it's associated with the aliased virtual variable.
|
||||
exists(OldInstruction oldInstruction | instruction = Chi(oldInstruction) |
|
||||
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
|
||||
Alias::AliasedVirtualVariable
|
||||
)
|
||||
or
|
||||
// Phi instructions track locations, and therefore a phi instruction is
|
||||
// conflated if it's associated with a conflated location.
|
||||
exists(Alias::MemoryLocation location |
|
||||
instruction = Phi(_, location) and
|
||||
not exists(location.getAllocation())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
|
||||
@@ -61,6 +61,11 @@ class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
class VirtualVariable extends MemoryLocation { }
|
||||
|
||||
/** A virtual variable that groups all escaped memory within a function. */
|
||||
class AliasedVirtualVariable extends VirtualVariable {
|
||||
AliasedVirtualVariable() { none() }
|
||||
}
|
||||
|
||||
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
def = use and result instanceof MustExactlyOverlap
|
||||
or
|
||||
|
||||
@@ -20,6 +20,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -20,6 +20,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -20,6 +20,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -20,6 +20,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -20,6 +20,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -824,41 +824,43 @@ ssa.cpp:
|
||||
# 184| m184_7(unsigned int &) = InitializeParameter[a] : &:r184_6
|
||||
# 184| r184_8(unsigned int &) = Load : &:r184_6, m184_7
|
||||
# 184| m184_9(unknown) = InitializeIndirection[a] : &:r184_8
|
||||
# 184| r184_10(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 184| m184_11(unsigned int &) = InitializeParameter[b] : &:r184_10
|
||||
# 184| r184_12(unsigned int &) = Load : &:r184_10, m184_11
|
||||
# 184| m184_13(unknown) = InitializeIndirection[b] : &:r184_12
|
||||
# 184| r184_14(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 184| m184_15(unsigned int &) = InitializeParameter[c] : &:r184_14
|
||||
# 184| r184_16(unsigned int &) = Load : &:r184_14, m184_15
|
||||
# 184| m184_17(unknown) = InitializeIndirection[c] : &:r184_16
|
||||
# 184| r184_18(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 184| m184_19(unsigned int &) = InitializeParameter[d] : &:r184_18
|
||||
# 184| r184_20(unsigned int &) = Load : &:r184_18, m184_19
|
||||
# 184| m184_21(unknown) = InitializeIndirection[d] : &:r184_20
|
||||
# 184| m184_10(unknown) = Chi : total:m184_4, partial:m184_9
|
||||
# 184| r184_11(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 184| m184_12(unsigned int &) = InitializeParameter[b] : &:r184_11
|
||||
# 184| r184_13(unsigned int &) = Load : &:r184_11, m184_12
|
||||
# 184| m184_14(unknown) = InitializeIndirection[b] : &:r184_13
|
||||
# 184| m184_15(unknown) = Chi : total:m184_10, partial:m184_14
|
||||
# 184| r184_16(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 184| m184_17(unsigned int &) = InitializeParameter[c] : &:r184_16
|
||||
# 184| r184_18(unsigned int &) = Load : &:r184_16, m184_17
|
||||
# 184| m184_19(unknown) = InitializeIndirection[c] : &:r184_18
|
||||
# 184| r184_20(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 184| m184_21(unsigned int &) = InitializeParameter[d] : &:r184_20
|
||||
# 184| r184_22(unsigned int &) = Load : &:r184_20, m184_21
|
||||
# 184| m184_23(unknown) = InitializeIndirection[d] : &:r184_22
|
||||
# 189| r189_1(glval<unsigned int &>) = VariableAddress[a] :
|
||||
# 189| r189_2(unsigned int &) = Load : &:r189_1, m184_7
|
||||
# 189| r189_3(glval<unsigned int>) = CopyValue : r189_2
|
||||
# 189| r189_4(glval<unsigned int &>) = VariableAddress[b] :
|
||||
# 189| r189_5(unsigned int &) = Load : &:r189_4, m184_11
|
||||
# 189| r189_5(unsigned int &) = Load : &:r189_4, m184_12
|
||||
# 189| r189_6(glval<unsigned int>) = CopyValue : r189_5
|
||||
# 190| r190_1(glval<unsigned int &>) = VariableAddress[c] :
|
||||
# 190| r190_2(unsigned int &) = Load : &:r190_1, m184_15
|
||||
# 190| r190_3(unsigned int) = Load : &:r190_2, ~m184_17
|
||||
# 190| r190_2(unsigned int &) = Load : &:r190_1, m184_17
|
||||
# 190| r190_3(unsigned int) = Load : &:r190_2, ~m184_19
|
||||
# 190| r190_4(glval<unsigned int &>) = VariableAddress[d] :
|
||||
# 190| r190_5(unsigned int &) = Load : &:r190_4, m184_19
|
||||
# 190| r190_6(unsigned int) = Load : &:r190_5, ~m184_21
|
||||
# 186| m186_1(unknown) = InlineAsm : ~m184_13, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
|
||||
# 186| m186_2(unknown) = Chi : total:m184_13, partial:m186_1
|
||||
# 190| r190_5(unsigned int &) = Load : &:r190_4, m184_21
|
||||
# 190| r190_6(unsigned int) = Load : &:r190_5, ~m184_23
|
||||
# 186| m186_1(unknown) = InlineAsm : ~m184_15, 0:r189_3, 1:r189_6, 2:r190_3, 3:r190_6
|
||||
# 186| m186_2(unknown) = Chi : total:m184_15, partial:m186_1
|
||||
# 192| v192_1(void) = NoOp :
|
||||
# 184| v184_22(void) = ReturnIndirection : &:r184_8, ~m186_2
|
||||
# 184| v184_23(void) = ReturnIndirection : &:r184_12, ~m186_2
|
||||
# 184| v184_24(void) = ReturnIndirection : &:r184_16, m184_17
|
||||
# 184| v184_25(void) = ReturnIndirection : &:r184_20, m184_21
|
||||
# 184| v184_26(void) = ReturnVoid :
|
||||
# 184| v184_27(void) = UnmodeledUse : mu*
|
||||
# 184| v184_28(void) = AliasedUse : ~m186_2
|
||||
# 184| v184_29(void) = ExitFunction :
|
||||
# 184| v184_24(void) = ReturnIndirection : &:r184_8, ~m186_2
|
||||
# 184| v184_25(void) = ReturnIndirection : &:r184_13, ~m186_2
|
||||
# 184| v184_26(void) = ReturnIndirection : &:r184_18, m184_19
|
||||
# 184| v184_27(void) = ReturnIndirection : &:r184_22, m184_23
|
||||
# 184| v184_28(void) = ReturnVoid :
|
||||
# 184| v184_29(void) = UnmodeledUse : mu*
|
||||
# 184| v184_30(void) = AliasedUse : ~m186_2
|
||||
# 184| v184_31(void) = ExitFunction :
|
||||
|
||||
# 198| int PureFunctions(char*, char*, int)
|
||||
# 198| Block 0
|
||||
@@ -1147,18 +1149,19 @@ ssa.cpp:
|
||||
# 247| m247_7(char *) = InitializeParameter[src] : &:r247_6
|
||||
# 247| r247_8(char *) = Load : &:r247_6, m247_7
|
||||
# 247| m247_9(unknown) = InitializeIndirection[src] : &:r247_8
|
||||
# 247| r247_10(glval<int>) = VariableAddress[size] :
|
||||
# 247| m247_11(int) = InitializeParameter[size] : &:r247_10
|
||||
# 247| m247_10(unknown) = Chi : total:m247_4, partial:m247_9
|
||||
# 247| r247_11(glval<int>) = VariableAddress[size] :
|
||||
# 247| m247_12(int) = InitializeParameter[size] : &:r247_11
|
||||
# 248| r248_1(glval<char *>) = VariableAddress[dst] :
|
||||
# 248| r248_2(glval<unknown>) = FunctionAddress[operator new[]] :
|
||||
# 248| r248_3(glval<int>) = VariableAddress[size] :
|
||||
# 248| r248_4(int) = Load : &:r248_3, m247_11
|
||||
# 248| r248_4(int) = Load : &:r248_3, m247_12
|
||||
# 248| r248_5(unsigned long) = Convert : r248_4
|
||||
# 248| r248_6(unsigned long) = Constant[1] :
|
||||
# 248| r248_7(unsigned long) = Mul : r248_5, r248_6
|
||||
# 248| r248_8(void *) = Call : func:r248_2, 0:r248_7
|
||||
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_9
|
||||
# 248| m248_10(unknown) = Chi : total:m247_9, partial:m248_9
|
||||
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_10
|
||||
# 248| m248_10(unknown) = Chi : total:m247_10, partial:m248_9
|
||||
# 248| r248_11(char *) = Convert : r248_8
|
||||
# 248| m248_12(char *) = Store : &:r248_1, r248_11
|
||||
# 249| r249_1(char) = Constant[97] :
|
||||
@@ -1175,7 +1178,7 @@ ssa.cpp:
|
||||
# 250| r250_6(char *) = Load : &:r250_5, m247_7
|
||||
# 250| r250_7(void *) = Convert : r250_6
|
||||
# 250| r250_8(glval<int>) = VariableAddress[size] :
|
||||
# 250| r250_9(int) = Load : &:r250_8, m247_11
|
||||
# 250| r250_9(int) = Load : &:r250_8, m247_12
|
||||
# 250| r250_10(void *) = Call : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9
|
||||
# 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6
|
||||
# 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9
|
||||
@@ -1184,12 +1187,12 @@ ssa.cpp:
|
||||
# 251| r251_2(glval<char *>) = VariableAddress[dst] :
|
||||
# 251| r251_3(char *) = Load : &:r251_2, m248_12
|
||||
# 251| m251_4(char *) = Store : &:r251_1, r251_3
|
||||
# 247| v247_12(void) = ReturnIndirection : &:r247_8, ~m250_13
|
||||
# 247| r247_13(glval<char *>) = VariableAddress[#return] :
|
||||
# 247| v247_14(void) = ReturnValue : &:r247_13, m251_4
|
||||
# 247| v247_15(void) = UnmodeledUse : mu*
|
||||
# 247| v247_16(void) = AliasedUse : ~m250_13
|
||||
# 247| v247_17(void) = ExitFunction :
|
||||
# 247| v247_13(void) = ReturnIndirection : &:r247_8, ~m250_13
|
||||
# 247| r247_14(glval<char *>) = VariableAddress[#return] :
|
||||
# 247| v247_15(void) = ReturnValue : &:r247_14, m251_4
|
||||
# 247| v247_16(void) = UnmodeledUse : mu*
|
||||
# 247| v247_17(void) = AliasedUse : ~m250_13
|
||||
# 247| v247_18(void) = ExitFunction :
|
||||
|
||||
# 254| char StringLiteralAliasing2(bool)
|
||||
# 254| Block 0
|
||||
@@ -1250,35 +1253,95 @@ ssa.cpp:
|
||||
# 268| m268_7(void *) = InitializeParameter[s] : &:r268_6
|
||||
# 268| r268_8(void *) = Load : &:r268_6, m268_7
|
||||
# 268| m268_9(unknown) = InitializeIndirection[s] : &:r268_8
|
||||
# 268| r268_10(glval<int>) = VariableAddress[size] :
|
||||
# 268| m268_11(int) = InitializeParameter[size] : &:r268_10
|
||||
# 268| m268_10(unknown) = Chi : total:m268_4, partial:m268_9
|
||||
# 268| r268_11(glval<int>) = VariableAddress[size] :
|
||||
# 268| m268_12(int) = InitializeParameter[size] : &:r268_11
|
||||
# 269| r269_1(glval<void *>) = VariableAddress[buf] :
|
||||
# 269| r269_2(glval<unknown>) = FunctionAddress[malloc] :
|
||||
# 269| r269_3(glval<int>) = VariableAddress[size] :
|
||||
# 269| r269_4(int) = Load : &:r269_3, m268_11
|
||||
# 269| r269_4(int) = Load : &:r269_3, m268_12
|
||||
# 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_6(unknown) = ^CallSideEffect : ~m268_10
|
||||
# 269| m269_7(unknown) = Chi : total:m268_10, partial:m269_6
|
||||
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
|
||||
# 269| m269_9(void *) = Store : &:r269_1, r269_5
|
||||
# 269| m269_9(unknown) = Chi : total:m269_7, partial:m269_8
|
||||
# 269| m269_10(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_9
|
||||
# 270| r270_3(void *) = Load : &:r270_2, m269_10
|
||||
# 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_7(int) = Load : &:r270_6, m268_12
|
||||
# 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_8
|
||||
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7
|
||||
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
|
||||
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
|
||||
# 270| m270_11(unknown) = Chi : total:m269_9, 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_9
|
||||
# 271| r271_3(void *) = Load : &:r271_2, m269_10
|
||||
# 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] :
|
||||
# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4
|
||||
# 268| v268_15(void) = UnmodeledUse : mu*
|
||||
# 268| v268_16(void) = AliasedUse : ~m270_11
|
||||
# 268| v268_17(void) = ExitFunction :
|
||||
# 268| v268_13(void) = ReturnIndirection : &:r268_8, ~m270_11
|
||||
# 268| r268_14(glval<void *>) = VariableAddress[#return] :
|
||||
# 268| v268_15(void) = ReturnValue : &:r268_14, m271_4
|
||||
# 268| v268_16(void) = UnmodeledUse : mu*
|
||||
# 268| v268_17(void) = AliasedUse : ~m270_11
|
||||
# 268| v268_18(void) = ExitFunction :
|
||||
|
||||
# 275| void EscapedButNotConflated(bool, Point, int)
|
||||
# 275| Block 0
|
||||
# 275| v275_1(void) = EnterFunction :
|
||||
# 275| m275_2(unknown) = AliasedDefinition :
|
||||
# 275| m275_3(unknown) = InitializeNonLocal :
|
||||
# 275| m275_4(unknown) = Chi : total:m275_2, partial:m275_3
|
||||
# 275| mu275_5(unknown) = UnmodeledDefinition :
|
||||
# 275| r275_6(glval<bool>) = VariableAddress[c] :
|
||||
# 275| m275_7(bool) = InitializeParameter[c] : &:r275_6
|
||||
# 275| r275_8(glval<Point>) = VariableAddress[p] :
|
||||
# 275| m275_9(Point) = InitializeParameter[p] : &:r275_8
|
||||
# 275| r275_10(glval<int>) = VariableAddress[x1] :
|
||||
# 275| m275_11(int) = InitializeParameter[x1] : &:r275_10
|
||||
# 276| r276_1(glval<Point>) = VariableAddress[a] :
|
||||
# 276| m276_2(Point) = Uninitialized[a] : &:r276_1
|
||||
# 276| m276_3(unknown) = Chi : total:m275_4, partial:m276_2
|
||||
# 276| r276_4(glval<int>) = FieldAddress[x] : r276_1
|
||||
# 276| r276_5(int) = Constant[0] :
|
||||
# 276| m276_6(int) = Store : &:r276_4, r276_5
|
||||
# 276| m276_7(unknown) = Chi : total:m276_3, partial:m276_6
|
||||
# 276| r276_8(glval<int>) = FieldAddress[y] : r276_1
|
||||
# 276| r276_9(int) = Constant[0] :
|
||||
# 276| m276_10(int) = Store : &:r276_8, r276_9
|
||||
# 276| m276_11(unknown) = Chi : total:m276_7, partial:m276_10
|
||||
# 277| r277_1(glval<Point>) = VariableAddress[a] :
|
||||
# 277| r277_2(Point *) = CopyValue : r277_1
|
||||
# 277| r277_3(glval<Point *>) = VariableAddress[pp] :
|
||||
# 277| m277_4(Point *) = Store : &:r277_3, r277_2
|
||||
# 277| m277_5(unknown) = Chi : total:m276_11, partial:m277_4
|
||||
# 278| r278_1(glval<bool>) = VariableAddress[c] :
|
||||
# 278| r278_2(bool) = Load : &:r278_1, m275_7
|
||||
# 278| v278_3(void) = ConditionalBranch : r278_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 279| Block 1
|
||||
# 279| r279_1(glval<int>) = VariableAddress[x1] :
|
||||
# 279| r279_2(int) = Load : &:r279_1, m275_11
|
||||
# 279| r279_3(glval<Point>) = VariableAddress[a] :
|
||||
# 279| r279_4(glval<int>) = FieldAddress[x] : r279_3
|
||||
# 279| m279_5(int) = Store : &:r279_4, r279_2
|
||||
# 279| m279_6(unknown) = Chi : total:m277_5, partial:m279_5
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 281| Block 2
|
||||
# 281| m281_1(int) = Phi : from 0:m276_6, from 1:m279_5
|
||||
# 281| m281_2(unknown) = Phi : from 0:~m277_5, from 1:~m279_6
|
||||
# 281| r281_3(glval<int>) = VariableAddress[x] :
|
||||
# 281| r281_4(glval<Point>) = VariableAddress[a] :
|
||||
# 281| r281_5(glval<int>) = FieldAddress[x] : r281_4
|
||||
# 281| r281_6(int) = Load : &:r281_5, m281_1
|
||||
# 281| m281_7(int) = Store : &:r281_3, r281_6
|
||||
# 282| v282_1(void) = NoOp :
|
||||
# 275| v275_12(void) = ReturnVoid :
|
||||
# 275| v275_13(void) = UnmodeledUse : mu*
|
||||
# 275| v275_14(void) = AliasedUse : ~m281_2
|
||||
# 275| v275_15(void) = ExitFunction :
|
||||
|
||||
@@ -1277,3 +1277,60 @@ ssa.cpp:
|
||||
# 268| v268_15(void) = UnmodeledUse : mu*
|
||||
# 268| v268_16(void) = AliasedUse : ~m269_7
|
||||
# 268| v268_17(void) = ExitFunction :
|
||||
|
||||
# 275| void EscapedButNotConflated(bool, Point, int)
|
||||
# 275| Block 0
|
||||
# 275| v275_1(void) = EnterFunction :
|
||||
# 275| m275_2(unknown) = AliasedDefinition :
|
||||
# 275| m275_3(unknown) = InitializeNonLocal :
|
||||
# 275| m275_4(unknown) = Chi : total:m275_2, partial:m275_3
|
||||
# 275| mu275_5(unknown) = UnmodeledDefinition :
|
||||
# 275| r275_6(glval<bool>) = VariableAddress[c] :
|
||||
# 275| m275_7(bool) = InitializeParameter[c] : &:r275_6
|
||||
# 275| r275_8(glval<Point>) = VariableAddress[p] :
|
||||
# 275| m275_9(Point) = InitializeParameter[p] : &:r275_8
|
||||
# 275| r275_10(glval<int>) = VariableAddress[x1] :
|
||||
# 275| m275_11(int) = InitializeParameter[x1] : &:r275_10
|
||||
# 276| r276_1(glval<Point>) = VariableAddress[a] :
|
||||
# 276| m276_2(Point) = Uninitialized[a] : &:r276_1
|
||||
# 276| r276_3(glval<int>) = FieldAddress[x] : r276_1
|
||||
# 276| r276_4(int) = Constant[0] :
|
||||
# 276| m276_5(int) = Store : &:r276_3, r276_4
|
||||
# 276| m276_6(Point) = Chi : total:m276_2, partial:m276_5
|
||||
# 276| r276_7(glval<int>) = FieldAddress[y] : r276_1
|
||||
# 276| r276_8(int) = Constant[0] :
|
||||
# 276| m276_9(int) = Store : &:r276_7, r276_8
|
||||
# 276| m276_10(Point) = Chi : total:m276_6, partial:m276_9
|
||||
# 277| r277_1(glval<Point>) = VariableAddress[a] :
|
||||
# 277| r277_2(Point *) = CopyValue : r277_1
|
||||
# 277| r277_3(glval<Point *>) = VariableAddress[pp] :
|
||||
# 277| m277_4(Point *) = Store : &:r277_3, r277_2
|
||||
# 277| m277_5(unknown) = Chi : total:m275_4, partial:m277_4
|
||||
# 278| r278_1(glval<bool>) = VariableAddress[c] :
|
||||
# 278| r278_2(bool) = Load : &:r278_1, m275_7
|
||||
# 278| v278_3(void) = ConditionalBranch : r278_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 279| Block 1
|
||||
# 279| r279_1(glval<int>) = VariableAddress[x1] :
|
||||
# 279| r279_2(int) = Load : &:r279_1, m275_11
|
||||
# 279| r279_3(glval<Point>) = VariableAddress[a] :
|
||||
# 279| r279_4(glval<int>) = FieldAddress[x] : r279_3
|
||||
# 279| m279_5(int) = Store : &:r279_4, r279_2
|
||||
# 279| m279_6(Point) = Chi : total:m276_10, partial:m279_5
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 281| Block 2
|
||||
# 281| m281_1(int) = Phi : from 0:m276_5, from 1:m279_5
|
||||
# 281| m281_2(Point) = Phi : from 0:m276_10, from 1:m279_6
|
||||
# 281| r281_3(glval<int>) = VariableAddress[x] :
|
||||
# 281| r281_4(glval<Point>) = VariableAddress[a] :
|
||||
# 281| r281_5(glval<int>) = FieldAddress[x] : r281_4
|
||||
# 281| r281_6(int) = Load : &:r281_5, m281_1
|
||||
# 281| m281_7(int) = Store : &:r281_3, r281_6
|
||||
# 282| v282_1(void) = NoOp :
|
||||
# 275| v275_12(void) = ReturnVoid :
|
||||
# 275| v275_13(void) = UnmodeledUse : mu*
|
||||
# 275| v275_14(void) = AliasedUse : ~m277_5
|
||||
# 275| v275_15(void) = ExitFunction :
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -269,4 +269,14 @@ void *MallocAliasing(void *s, int size) {
|
||||
void *buf = malloc(size);
|
||||
memcpy(buf, s, size);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
Point *pp;
|
||||
void EscapedButNotConflated(bool c, Point p, int x1) {
|
||||
Point a = {};
|
||||
pp = &a; // `a` escapes here and therefore belongs to the aliased vvar
|
||||
if (c) {
|
||||
a.x = x1;
|
||||
}
|
||||
int x = a.x; // The phi node here is not conflated
|
||||
}
|
||||
|
||||
@@ -1188,3 +1188,53 @@ ssa.cpp:
|
||||
# 268| v268_14(void) = UnmodeledUse : mu*
|
||||
# 268| v268_15(void) = AliasedUse : ~mu268_4
|
||||
# 268| v268_16(void) = ExitFunction :
|
||||
|
||||
# 275| void EscapedButNotConflated(bool, Point, int)
|
||||
# 275| Block 0
|
||||
# 275| v275_1(void) = EnterFunction :
|
||||
# 275| mu275_2(unknown) = AliasedDefinition :
|
||||
# 275| mu275_3(unknown) = InitializeNonLocal :
|
||||
# 275| mu275_4(unknown) = UnmodeledDefinition :
|
||||
# 275| r275_5(glval<bool>) = VariableAddress[c] :
|
||||
# 275| m275_6(bool) = InitializeParameter[c] : &:r275_5
|
||||
# 275| r275_7(glval<Point>) = VariableAddress[p] :
|
||||
# 275| m275_8(Point) = InitializeParameter[p] : &:r275_7
|
||||
# 275| r275_9(glval<int>) = VariableAddress[x1] :
|
||||
# 275| m275_10(int) = InitializeParameter[x1] : &:r275_9
|
||||
# 276| r276_1(glval<Point>) = VariableAddress[a] :
|
||||
# 276| mu276_2(Point) = Uninitialized[a] : &:r276_1
|
||||
# 276| r276_3(glval<int>) = FieldAddress[x] : r276_1
|
||||
# 276| r276_4(int) = Constant[0] :
|
||||
# 276| mu276_5(int) = Store : &:r276_3, r276_4
|
||||
# 276| r276_6(glval<int>) = FieldAddress[y] : r276_1
|
||||
# 276| r276_7(int) = Constant[0] :
|
||||
# 276| mu276_8(int) = Store : &:r276_6, r276_7
|
||||
# 277| r277_1(glval<Point>) = VariableAddress[a] :
|
||||
# 277| r277_2(Point *) = CopyValue : r277_1
|
||||
# 277| r277_3(glval<Point *>) = VariableAddress[pp] :
|
||||
# 277| mu277_4(Point *) = Store : &:r277_3, r277_2
|
||||
# 278| r278_1(glval<bool>) = VariableAddress[c] :
|
||||
# 278| r278_2(bool) = Load : &:r278_1, m275_6
|
||||
# 278| v278_3(void) = ConditionalBranch : r278_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 279| Block 1
|
||||
# 279| r279_1(glval<int>) = VariableAddress[x1] :
|
||||
# 279| r279_2(int) = Load : &:r279_1, m275_10
|
||||
# 279| r279_3(glval<Point>) = VariableAddress[a] :
|
||||
# 279| r279_4(glval<int>) = FieldAddress[x] : r279_3
|
||||
# 279| mu279_5(int) = Store : &:r279_4, r279_2
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 281| Block 2
|
||||
# 281| r281_1(glval<int>) = VariableAddress[x] :
|
||||
# 281| r281_2(glval<Point>) = VariableAddress[a] :
|
||||
# 281| r281_3(glval<int>) = FieldAddress[x] : r281_2
|
||||
# 281| r281_4(int) = Load : &:r281_3, ~mu275_4
|
||||
# 281| m281_5(int) = Store : &:r281_1, r281_4
|
||||
# 282| v282_1(void) = NoOp :
|
||||
# 275| v275_11(void) = ReturnVoid :
|
||||
# 275| v275_12(void) = UnmodeledUse : mu*
|
||||
# 275| v275_13(void) = AliasedUse : ~mu275_4
|
||||
# 275| v275_14(void) = ExitFunction :
|
||||
|
||||
@@ -1188,3 +1188,53 @@ ssa.cpp:
|
||||
# 268| v268_14(void) = UnmodeledUse : mu*
|
||||
# 268| v268_15(void) = AliasedUse : ~mu268_4
|
||||
# 268| v268_16(void) = ExitFunction :
|
||||
|
||||
# 275| void EscapedButNotConflated(bool, Point, int)
|
||||
# 275| Block 0
|
||||
# 275| v275_1(void) = EnterFunction :
|
||||
# 275| mu275_2(unknown) = AliasedDefinition :
|
||||
# 275| mu275_3(unknown) = InitializeNonLocal :
|
||||
# 275| mu275_4(unknown) = UnmodeledDefinition :
|
||||
# 275| r275_5(glval<bool>) = VariableAddress[c] :
|
||||
# 275| m275_6(bool) = InitializeParameter[c] : &:r275_5
|
||||
# 275| r275_7(glval<Point>) = VariableAddress[p] :
|
||||
# 275| m275_8(Point) = InitializeParameter[p] : &:r275_7
|
||||
# 275| r275_9(glval<int>) = VariableAddress[x1] :
|
||||
# 275| m275_10(int) = InitializeParameter[x1] : &:r275_9
|
||||
# 276| r276_1(glval<Point>) = VariableAddress[a] :
|
||||
# 276| mu276_2(Point) = Uninitialized[a] : &:r276_1
|
||||
# 276| r276_3(glval<int>) = FieldAddress[x] : r276_1
|
||||
# 276| r276_4(int) = Constant[0] :
|
||||
# 276| mu276_5(int) = Store : &:r276_3, r276_4
|
||||
# 276| r276_6(glval<int>) = FieldAddress[y] : r276_1
|
||||
# 276| r276_7(int) = Constant[0] :
|
||||
# 276| mu276_8(int) = Store : &:r276_6, r276_7
|
||||
# 277| r277_1(glval<Point>) = VariableAddress[a] :
|
||||
# 277| r277_2(Point *) = CopyValue : r277_1
|
||||
# 277| r277_3(glval<Point *>) = VariableAddress[pp] :
|
||||
# 277| mu277_4(Point *) = Store : &:r277_3, r277_2
|
||||
# 278| r278_1(glval<bool>) = VariableAddress[c] :
|
||||
# 278| r278_2(bool) = Load : &:r278_1, m275_6
|
||||
# 278| v278_3(void) = ConditionalBranch : r278_2
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 279| Block 1
|
||||
# 279| r279_1(glval<int>) = VariableAddress[x1] :
|
||||
# 279| r279_2(int) = Load : &:r279_1, m275_10
|
||||
# 279| r279_3(glval<Point>) = VariableAddress[a] :
|
||||
# 279| r279_4(glval<int>) = FieldAddress[x] : r279_3
|
||||
# 279| mu279_5(int) = Store : &:r279_4, r279_2
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 281| Block 2
|
||||
# 281| r281_1(glval<int>) = VariableAddress[x] :
|
||||
# 281| r281_2(glval<Point>) = VariableAddress[a] :
|
||||
# 281| r281_3(glval<int>) = FieldAddress[x] : r281_2
|
||||
# 281| r281_4(int) = Load : &:r281_3, ~mu275_4
|
||||
# 281| m281_5(int) = Store : &:r281_1, r281_4
|
||||
# 282| v282_1(void) = NoOp :
|
||||
# 275| v275_11(void) = ReturnVoid :
|
||||
# 275| v275_12(void) = UnmodeledUse : mu*
|
||||
# 275| v275_13(void) = AliasedUse : ~mu275_4
|
||||
# 275| v275_14(void) = ExitFunction :
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -568,6 +568,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -631,6 +631,8 @@ useNotDominatedByDefinition
|
||||
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) |
|
||||
| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) |
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -577,6 +577,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -274,6 +274,36 @@ module InstructionSanity {
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
|
||||
* memory.
|
||||
*/
|
||||
private predicate isOnAliasedDefinitionChain(Instruction instr) {
|
||||
instr instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate shouldBeConflated(Instruction instr) {
|
||||
isOnAliasedDefinitionChain(instr)
|
||||
or
|
||||
instr instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instr.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
query predicate notMarkedAsConflated(Instruction instr) {
|
||||
shouldBeConflated(instr) and
|
||||
not instr.isResultConflated()
|
||||
}
|
||||
|
||||
query predicate wronglyMarkedAsConflated(Instruction instr) {
|
||||
instr.isResultConflated() and
|
||||
not shouldBeConflated(instr)
|
||||
}
|
||||
|
||||
query predicate invalidOverlap(
|
||||
MemoryOperand useOperand, string message, IRFunction func, string funcText
|
||||
) {
|
||||
|
||||
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is an instruction with a memory result that represents a
|
||||
* conflation of more than one memory allocation.
|
||||
*
|
||||
* This happens in practice when dereferencing a pointer that cannot be
|
||||
* tracked back to a single local allocation. Such memory is instead modeled
|
||||
* as originating on the `AliasedDefinitionInstruction` at the entry of the
|
||||
* function.
|
||||
*/
|
||||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
|
||||
|
||||
/**
|
||||
* Gets the successor of this instruction along the control flow edge
|
||||
* specified by `kind`.
|
||||
|
||||
@@ -69,6 +69,15 @@ private module Cached {
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
cached
|
||||
predicate hasConflatedMemoryResult(Instruction instruction) {
|
||||
instruction instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instruction instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
cached
|
||||
Expr getInstructionConvertedResultExpression(Instruction instruction) {
|
||||
exists(TranslatedExpr translatedExpr |
|
||||
|
||||
@@ -274,6 +274,36 @@ module InstructionSanity {
|
||||
funcText = Language::getIdentityString(func.getFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is on the chain of chi/phi instructions for all aliased
|
||||
* memory.
|
||||
*/
|
||||
private predicate isOnAliasedDefinitionChain(Instruction instr) {
|
||||
instr instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(ChiInstruction).getTotal())
|
||||
or
|
||||
isOnAliasedDefinitionChain(instr.(PhiInstruction).getAnInputOperand().getAnyDef())
|
||||
}
|
||||
|
||||
private predicate shouldBeConflated(Instruction instr) {
|
||||
isOnAliasedDefinitionChain(instr)
|
||||
or
|
||||
instr instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instr.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
}
|
||||
|
||||
query predicate notMarkedAsConflated(Instruction instr) {
|
||||
shouldBeConflated(instr) and
|
||||
not instr.isResultConflated()
|
||||
}
|
||||
|
||||
query predicate wronglyMarkedAsConflated(Instruction instr) {
|
||||
instr.isResultConflated() and
|
||||
not shouldBeConflated(instr)
|
||||
}
|
||||
|
||||
query predicate invalidOverlap(
|
||||
MemoryOperand useOperand, string message, IRFunction func, string funcText
|
||||
) {
|
||||
|
||||
@@ -338,6 +338,17 @@ class Instruction extends Construction::TInstruction {
|
||||
Construction::hasModeledMemoryResult(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is an instruction with a memory result that represents a
|
||||
* conflation of more than one memory allocation.
|
||||
*
|
||||
* This happens in practice when dereferencing a pointer that cannot be
|
||||
* tracked back to a single local allocation. Such memory is instead modeled
|
||||
* as originating on the `AliasedDefinitionInstruction` at the entry of the
|
||||
* function.
|
||||
*/
|
||||
final predicate isResultConflated() { Construction::hasConflatedMemoryResult(this) }
|
||||
|
||||
/**
|
||||
* Gets the successor of this instruction along the control flow edge
|
||||
* specified by `kind`.
|
||||
|
||||
@@ -65,6 +65,29 @@ private module Cached {
|
||||
instruction instanceof ChiInstruction // Chis always have modeled results
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasConflatedMemoryResult(Instruction instruction) {
|
||||
instruction instanceof UnmodeledDefinitionInstruction
|
||||
or
|
||||
instruction instanceof AliasedDefinitionInstruction
|
||||
or
|
||||
instruction.getOpcode() instanceof Opcode::InitializeNonLocal
|
||||
or
|
||||
// Chi instructions track virtual variables, and therefore a chi instruction is
|
||||
// conflated if it's associated with the aliased virtual variable.
|
||||
exists(OldInstruction oldInstruction | instruction = Chi(oldInstruction) |
|
||||
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
|
||||
Alias::AliasedVirtualVariable
|
||||
)
|
||||
or
|
||||
// Phi instructions track locations, and therefore a phi instruction is
|
||||
// conflated if it's associated with a conflated location.
|
||||
exists(Alias::MemoryLocation location |
|
||||
instruction = Phi(_, location) and
|
||||
not exists(location.getAllocation())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
|
||||
@@ -61,6 +61,11 @@ class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
class VirtualVariable extends MemoryLocation { }
|
||||
|
||||
/** A virtual variable that groups all escaped memory within a function. */
|
||||
class AliasedVirtualVariable extends VirtualVariable {
|
||||
AliasedVirtualVariable() { none() }
|
||||
}
|
||||
|
||||
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
def = use and result instanceof MustExactlyOverlap
|
||||
or
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -16,6 +16,8 @@ lostReachability
|
||||
backEdgeCountMismatch
|
||||
useNotDominatedByDefinition
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
wronglyMarkedAsConflated
|
||||
invalidOverlap
|
||||
missingCanonicalLanguageType
|
||||
multipleCanonicalLanguageTypes
|
||||
|
||||
@@ -366,6 +366,16 @@ public class E
|
||||
static int Ex34(string s = null) => s.Length; // BAD (maybe)
|
||||
|
||||
static int Ex35(string s = "null") => s.Length; // GOOD
|
||||
|
||||
static int Ex36(object o)
|
||||
{
|
||||
if (o is string)
|
||||
{
|
||||
var s = o as string;
|
||||
return s.Length; // GOOD (false positive)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Extensions
|
||||
|
||||
@@ -1231,6 +1231,11 @@
|
||||
| E.cs:362:18:362:29 | (...) ... | null | E.cs:362:26:362:29 | null | null |
|
||||
| E.cs:363:13:363:13 | access to local variable x | non-null | E.cs:361:17:361:32 | ... ?? ... | non-null |
|
||||
| E.cs:363:13:363:13 | access to local variable x | null | E.cs:361:17:361:32 | ... ?? ... | null |
|
||||
| E.cs:372:13:372:23 | ... is ... | true | E.cs:372:13:372:13 | access to parameter o | non-null |
|
||||
| E.cs:375:20:375:20 | access to local variable s | empty | E.cs:374:21:374:31 | ... as ... | empty |
|
||||
| E.cs:375:20:375:20 | access to local variable s | non-empty | E.cs:374:21:374:31 | ... as ... | non-empty |
|
||||
| E.cs:375:20:375:20 | access to local variable s | non-null | E.cs:374:21:374:31 | ... as ... | non-null |
|
||||
| E.cs:375:20:375:20 | access to local variable s | null | E.cs:374:21:374:31 | ... as ... | null |
|
||||
| Forwarding.cs:9:13:9:30 | !... | false | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | true |
|
||||
| Forwarding.cs:9:13:9:30 | !... | true | Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | false |
|
||||
| Forwarding.cs:9:14:9:14 | access to local variable s | empty | Forwarding.cs:7:20:7:23 | null | empty |
|
||||
|
||||
@@ -263,6 +263,7 @@
|
||||
| E.cs:361:17:361:17 | access to parameter s | E.cs:361:17:361:17 | access to parameter s | null | true |
|
||||
| E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | false | true |
|
||||
| E.cs:362:13:362:29 | ... != ... | E.cs:362:13:362:13 | access to local variable x | true | false |
|
||||
| E.cs:372:13:372:23 | ... is ... | E.cs:372:13:372:13 | access to parameter o | true | false |
|
||||
| Forwarding.cs:9:14:9:30 | call to method IsNullOrEmpty | Forwarding.cs:9:14:9:14 | access to local variable s | false | false |
|
||||
| Forwarding.cs:14:13:14:32 | call to method IsNotNullOrEmpty | Forwarding.cs:14:13:14:13 | access to local variable s | true | false |
|
||||
| Forwarding.cs:19:14:19:23 | call to method IsNull | Forwarding.cs:19:14:19:14 | access to local variable s | false | false |
|
||||
|
||||
@@ -353,6 +353,8 @@ nodes
|
||||
| E.cs:349:9:349:9 | access to local variable x |
|
||||
| E.cs:366:28:366:28 | SSA param(s) |
|
||||
| E.cs:366:41:366:41 | access to parameter s |
|
||||
| E.cs:374:17:374:31 | SSA def(s) |
|
||||
| E.cs:375:20:375:20 | access to local variable s |
|
||||
| Forwarding.cs:7:16:7:23 | SSA def(s) |
|
||||
| Forwarding.cs:14:9:17:9 | if (...) ... |
|
||||
| Forwarding.cs:19:9:22:9 | if (...) ... |
|
||||
@@ -685,6 +687,7 @@ edges
|
||||
| E.cs:342:13:342:32 | SSA def(x) | E.cs:343:9:343:9 | access to local variable x |
|
||||
| E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x |
|
||||
| E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s |
|
||||
| E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s |
|
||||
| Forwarding.cs:7:16:7:23 | SSA def(s) | Forwarding.cs:14:9:17:9 | if (...) ... |
|
||||
| Forwarding.cs:14:9:17:9 | if (...) ... | Forwarding.cs:19:9:22:9 | if (...) ... |
|
||||
| Forwarding.cs:19:9:22:9 | if (...) ... | Forwarding.cs:24:9:27:9 | if (...) ... |
|
||||
@@ -786,6 +789,7 @@ edges
|
||||
| E.cs:343:9:343:9 | access to local variable x | E.cs:342:13:342:32 | SSA def(x) | E.cs:343:9:343:9 | access to local variable x | Variable $@ may be null here because of $@ assignment. | E.cs:342:13:342:13 | x | x | E.cs:342:13:342:32 | String x = ... | this |
|
||||
| E.cs:349:9:349:9 | access to local variable x | E.cs:348:17:348:36 | SSA def(x) | E.cs:349:9:349:9 | access to local variable x | Variable $@ may be null here because of $@ assignment. | E.cs:348:17:348:17 | x | x | E.cs:348:17:348:36 | dynamic x = ... | this |
|
||||
| E.cs:366:41:366:41 | access to parameter s | E.cs:366:28:366:28 | SSA param(s) | E.cs:366:41:366:41 | access to parameter s | Variable $@ may be null here because the parameter has a null default value. | E.cs:366:28:366:28 | s | s | E.cs:366:32:366:35 | null | this |
|
||||
| E.cs:375:20:375:20 | access to local variable s | E.cs:374:17:374:31 | SSA def(s) | E.cs:375:20:375:20 | access to local variable s | Variable $@ may be null here because of $@ assignment. | E.cs:374:17:374:17 | s | s | E.cs:374:17:374:31 | String s = ... | this |
|
||||
| GuardedString.cs:35:31:35:31 | access to local variable s | GuardedString.cs:7:16:7:32 | SSA def(s) | GuardedString.cs:35:31:35:31 | access to local variable s | Variable $@ may be null here because of $@ assignment. | GuardedString.cs:7:16:7:16 | s | s | GuardedString.cs:7:16:7:32 | String s = ... | this |
|
||||
| NullMaybeBad.cs:7:27:7:27 | access to parameter o | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | Variable $@ may be null here because of $@ null argument. | NullMaybeBad.cs:5:25:5:25 | o | o | NullMaybeBad.cs:13:17:13:20 | null | this |
|
||||
| StringConcatenation.cs:16:17:16:17 | access to local variable s | StringConcatenation.cs:14:16:14:23 | SSA def(s) | StringConcatenation.cs:16:17:16:17 | access to local variable s | Variable $@ may be null here because of $@ assignment. | StringConcatenation.cs:14:16:14:16 | s | s | StringConcatenation.cs:14:16:14:23 | String s = ... | this |
|
||||
|
||||
@@ -132,15 +132,22 @@ private module Postgres {
|
||||
result = DataFlow::moduleImport("pg-pool").getAnInstantiation()
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode clientOrPool(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
(result = client() or result = newPool())
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = clientOrPool(t2).track(t2, t))
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode clientOrPool() {
|
||||
result = clientOrPool(DataFlow::TypeTracker::end())
|
||||
}
|
||||
|
||||
/** A call to the Postgres `query` method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::ValueNode {
|
||||
override MethodCallExpr astNode;
|
||||
|
||||
QueryCall() {
|
||||
exists(DataFlow::SourceNode recv | recv = client() or recv = newPool() |
|
||||
this = recv.getAMethodCall("query")
|
||||
)
|
||||
}
|
||||
QueryCall() { this = clientOrPool().getAMethodCall("query") }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = DataFlow::valueNode(astNode.getArgument(0))
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
| postgres1.js:37:21:37:24 | text |
|
||||
| postgres2.js:30:16:30:41 | 'SELECT ... number' |
|
||||
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
|
||||
| postgres5.js:8:21:8:25 | query |
|
||||
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
|
||||
| sequelize.js:8:17:8:118 | 'SELECT ... Y name' |
|
||||
| spanner2.js:5:26:5:35 | "SQL code" |
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
const pg = require('pg');
|
||||
|
||||
function PgWrapper() {
|
||||
this.pool = new pg.Pool({});
|
||||
}
|
||||
|
||||
PgWrapper.prototype.query = function (query, params, cb) {
|
||||
this.pool.query(query, params || [], cb);
|
||||
};
|
||||
Reference in New Issue
Block a user