mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
C++: Add conservative side effects for function calls
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import cpp
|
||||
|
||||
newtype TMemoryAccessKind =
|
||||
private newtype TMemoryAccessKind =
|
||||
TIndirectMemoryAccess() or
|
||||
TIndirectMayMemoryAccess() or
|
||||
TBufferMemoryAccess() or
|
||||
TBufferMayMemoryAccess() or
|
||||
TEscapedMemoryAccess() or
|
||||
TPhiMemoryAccess() or
|
||||
TUnmodeledMemoryAccess()
|
||||
@@ -15,8 +18,8 @@ class MemoryAccessKind extends TMemoryAccessKind {
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand or result accesses memory at the address specified by the
|
||||
* `AddressOperand` on the same instruction.
|
||||
* The operand or result accesses memory at the address specified by the `AddressOperand` on the
|
||||
* same instruction.
|
||||
*/
|
||||
class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
|
||||
override string toString() {
|
||||
@@ -24,6 +27,38 @@ class IndirectMemoryAccess extends MemoryAccessKind, TIndirectMemoryAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand or result may access some, all, or none of the memory at the address specified by the
|
||||
* `AddressOperand` on the same instruction.
|
||||
*/
|
||||
class IndirectMayMemoryAccess extends MemoryAccessKind, TIndirectMayMemoryAccess {
|
||||
override string toString() {
|
||||
result = "indirect(may)"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand or result accesses memory starting at the address specified by the `AddressOperand`
|
||||
* on the same instruction, accessing a number of consecutive elements given by the
|
||||
* `BufferSizeOperand`.
|
||||
*/
|
||||
class BufferMemoryAccess extends MemoryAccessKind, TBufferMemoryAccess {
|
||||
override string toString() {
|
||||
result = "buffer"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand or result may access some, all, or none of the memory starting at the address
|
||||
* specified by the `AddressOperand` on the same instruction, accessing a number of consecutive
|
||||
* elements given by the `BufferSizeOperand`.
|
||||
*/
|
||||
class BufferMayMemoryAccess extends MemoryAccessKind, TBufferMayMemoryAccess {
|
||||
override string toString() {
|
||||
result = "buffer(may)"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand or result accesses all memory whose address has escaped.
|
||||
*/
|
||||
|
||||
@@ -58,7 +58,15 @@ private newtype TOpcode =
|
||||
TVarArgsStart() or
|
||||
TVarArgsEnd() or
|
||||
TVarArg() or
|
||||
TVarArgCopy()
|
||||
TVarArgCopy() or
|
||||
TCallSideEffect() or
|
||||
TCallReadSideEffect() or
|
||||
TIndirectReadSideEffect() or
|
||||
TIndirectWriteSideEffect() or
|
||||
TIndirectMayWriteSideEffect() or
|
||||
TBufferReadSideEffect() or
|
||||
TBufferWriteSideEffect() or
|
||||
TBufferMayWriteSideEffect()
|
||||
|
||||
class Opcode extends TOpcode {
|
||||
string toString() {
|
||||
@@ -92,6 +100,29 @@ abstract class OpcodeWithCondition extends Opcode {}
|
||||
|
||||
abstract class BuiltInOpcode extends Opcode {}
|
||||
|
||||
abstract class SideEffectOpcode extends Opcode {}
|
||||
|
||||
/**
|
||||
* An opcode that reads from a set of memory locations as a side effect.
|
||||
*/
|
||||
abstract class ReadSideEffectOpcode extends SideEffectOpcode {}
|
||||
|
||||
/**
|
||||
* An opcode that writes to a set of memory locations as a side effect.
|
||||
*/
|
||||
abstract class WriteSideEffectOpcode extends SideEffectOpcode {}
|
||||
|
||||
/**
|
||||
* An opcode that may overwrite some, all, or none of an existing set of memory locations. Modeled
|
||||
* as a read of the original contents, plus a "may" write of the new contents.
|
||||
*/
|
||||
abstract class MayWriteSideEffectOpcode extends SideEffectOpcode {}
|
||||
|
||||
/**
|
||||
* An opcode that accesses a buffer via an `AddressOperand` and a `BufferSizeOperand`.
|
||||
*/
|
||||
abstract class BufferAccessOpcode extends MemoryAccessOpcode {}
|
||||
|
||||
module Opcode {
|
||||
class NoOp extends Opcode, TNoOp { override final string toString() { result = "NoOp" } }
|
||||
class Uninitialized extends MemoryAccessOpcode, TUninitialized { override final string toString() { result = "Uninitialized" } }
|
||||
@@ -153,4 +184,12 @@ module Opcode {
|
||||
class VarArgsEnd extends BuiltInOpcode, TVarArgsEnd { override final string toString() { result = "VarArgsEnd" } }
|
||||
class VarArg extends BuiltInOpcode, TVarArg { override final string toString() { result = "VarArg" } }
|
||||
class VarArgCopy extends BuiltInOpcode, TVarArgCopy { override final string toString() { result = "VarArgCopy" } }
|
||||
class CallSideEffect extends MayWriteSideEffectOpcode, TCallSideEffect { override final string toString() { result = "CallSideEffect" } }
|
||||
class CallReadSideEffect extends ReadSideEffectOpcode, TCallReadSideEffect { override final string toString() { result = "CallReadSideEffect" } }
|
||||
class IndirectReadSideEffect extends ReadSideEffectOpcode, MemoryAccessOpcode, TIndirectReadSideEffect { override final string toString() { result = "IndirectReadSideEffect" } }
|
||||
class IndirectWriteSideEffect extends WriteSideEffectOpcode, MemoryAccessOpcode, TIndirectWriteSideEffect { override final string toString() { result = "IndirectWriteSideEffect" } }
|
||||
class IndirectMayWriteSideEffect extends MayWriteSideEffectOpcode, MemoryAccessOpcode, TIndirectMayWriteSideEffect { override final string toString() { result = "IndirectMayWriteSideEffect" } }
|
||||
class BufferReadSideEffect extends ReadSideEffectOpcode, BufferAccessOpcode, TBufferReadSideEffect { override final string toString() { result = "BufferReadSideEffect" } }
|
||||
class BufferWriteSideEffect extends WriteSideEffectOpcode, BufferAccessOpcode, TBufferWriteSideEffect { override final string toString() { result = "BufferWriteSideEffect" } }
|
||||
class BufferMayWriteSideEffect extends MayWriteSideEffectOpcode, BufferAccessOpcode, TBufferMayWriteSideEffect { override final string toString() { result = "BufferMayWriteSideEffect" } }
|
||||
}
|
||||
|
||||
@@ -33,11 +33,16 @@ module InstructionSanity {
|
||||
) or
|
||||
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
|
||||
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
|
||||
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
|
||||
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
|
||||
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
|
||||
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
|
||||
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
|
||||
(
|
||||
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
|
||||
tag instanceof SideEffectOperandTag
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*/
|
||||
final string getOperationString() {
|
||||
if exists(getImmediateString()) then
|
||||
result = opcode.toString() + "[" + getImmediateString() + "]"
|
||||
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
|
||||
else
|
||||
result = opcode.toString()
|
||||
result = getOperationPrefix() + opcode.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
|
||||
none()
|
||||
}
|
||||
|
||||
private string getOperationPrefix() {
|
||||
if this instanceof SideEffectInstruction then
|
||||
result = "^"
|
||||
else
|
||||
result = ""
|
||||
}
|
||||
|
||||
private string getResultPrefix() {
|
||||
if resultType instanceof VoidType then
|
||||
result = "v"
|
||||
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that calls a function.
|
||||
*/
|
||||
class CallInstruction extends Instruction {
|
||||
CallInstruction() {
|
||||
opcode instanceof Opcode::Call
|
||||
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() {
|
||||
opcode instanceof SideEffectOpcode
|
||||
}
|
||||
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be
|
||||
* accessed by that call.
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof EscapedMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be read
|
||||
* by that call.
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect buffer parameter within a function call.
|
||||
*/
|
||||
class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call. The
|
||||
* entire buffer is overwritten.
|
||||
*/
|
||||
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the potential write of an indirect parameter within a function call.
|
||||
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
|
||||
* written.
|
||||
*/
|
||||
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectMayWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call.
|
||||
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
|
||||
*/
|
||||
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferMayWriteSideEffect
|
||||
}
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that throws an exception.
|
||||
*/
|
||||
|
||||
@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
}
|
||||
}
|
||||
|
||||
class SideEffectOperand extends NonPhiOperand {
|
||||
SideEffectOperand() {
|
||||
this = TNonPhiOperand(_, sideEffectOperand(), _)
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
instr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof CallReadSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectReadSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferReadSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectWriteSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferWriteSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectMayWriteSideEffectInstruction and
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
or
|
||||
instr instanceof BufferMayWriteSideEffectInstruction and
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of a `PhiInstruction`.
|
||||
*/
|
||||
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An operand that reads a value from memory.
|
||||
*/
|
||||
|
||||
@@ -227,6 +227,13 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
exists(OldIR::SideEffectInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
|
||||
block.getInstruction(index) = instr and
|
||||
|
||||
@@ -33,11 +33,16 @@ module InstructionSanity {
|
||||
) or
|
||||
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
|
||||
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
|
||||
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
|
||||
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
|
||||
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
|
||||
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
|
||||
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
|
||||
(
|
||||
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
|
||||
tag instanceof SideEffectOperandTag
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*/
|
||||
final string getOperationString() {
|
||||
if exists(getImmediateString()) then
|
||||
result = opcode.toString() + "[" + getImmediateString() + "]"
|
||||
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
|
||||
else
|
||||
result = opcode.toString()
|
||||
result = getOperationPrefix() + opcode.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
|
||||
none()
|
||||
}
|
||||
|
||||
private string getOperationPrefix() {
|
||||
if this instanceof SideEffectInstruction then
|
||||
result = "^"
|
||||
else
|
||||
result = ""
|
||||
}
|
||||
|
||||
private string getResultPrefix() {
|
||||
if resultType instanceof VoidType then
|
||||
result = "v"
|
||||
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that calls a function.
|
||||
*/
|
||||
class CallInstruction extends Instruction {
|
||||
CallInstruction() {
|
||||
opcode instanceof Opcode::Call
|
||||
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() {
|
||||
opcode instanceof SideEffectOpcode
|
||||
}
|
||||
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be
|
||||
* accessed by that call.
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof EscapedMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be read
|
||||
* by that call.
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect buffer parameter within a function call.
|
||||
*/
|
||||
class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call. The
|
||||
* entire buffer is overwritten.
|
||||
*/
|
||||
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the potential write of an indirect parameter within a function call.
|
||||
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
|
||||
* written.
|
||||
*/
|
||||
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectMayWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call.
|
||||
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
|
||||
*/
|
||||
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferMayWriteSideEffect
|
||||
}
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that throws an exception.
|
||||
*/
|
||||
|
||||
@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
}
|
||||
}
|
||||
|
||||
class SideEffectOperand extends NonPhiOperand {
|
||||
SideEffectOperand() {
|
||||
this = TNonPhiOperand(_, sideEffectOperand(), _)
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
instr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof CallReadSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectReadSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferReadSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectWriteSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferWriteSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectMayWriteSideEffectInstruction and
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
or
|
||||
instr instanceof BufferMayWriteSideEffectInstruction and
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of a `PhiInstruction`.
|
||||
*/
|
||||
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An operand that reads a value from memory.
|
||||
*/
|
||||
|
||||
@@ -167,6 +167,13 @@ cached private module Cached {
|
||||
result = element.getInstructionResultSize(tag)
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
exists(TranslatedElement element, InstructionTag tag |
|
||||
instructionOrigin(instruction, element, tag) and
|
||||
result = element.getPrimaryInstructionForSideEffect(tag)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
@@ -43,6 +43,7 @@ newtype TInstructionTag =
|
||||
SwitchBranchTag() or
|
||||
CallTargetTag() or
|
||||
CallTag() or
|
||||
CallSideEffectTag() or
|
||||
AllocationSizeTag() or
|
||||
AllocationElementSizeTag() or
|
||||
AllocationExtentConvertTag() or
|
||||
@@ -113,6 +114,7 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = SwitchBranchTag() and result = "SwitchBranch" or
|
||||
tag = CallTargetTag() and result = "CallTarget" or
|
||||
tag = CallTag() and result = "Call" or
|
||||
tag = CallSideEffectTag() and result = "CallSideEffect" or
|
||||
tag = AllocationSizeTag() and result = "AllocSize" or
|
||||
tag = AllocationElementSizeTag() and result = "AllocElemSize" or
|
||||
tag = AllocationExtentConvertTag() and result = "AllocExtConv" or
|
||||
|
||||
@@ -534,6 +534,14 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the primary instruction for the side effect instruction that was
|
||||
* generated by this element for tag `tag`.
|
||||
*/
|
||||
Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element generates a temporary variable with type `type`.
|
||||
* `tag` must be unique for each variable generated from the same AST node
|
||||
|
||||
@@ -33,11 +33,16 @@ module InstructionSanity {
|
||||
) or
|
||||
opcode instanceof CopyOpcode and tag instanceof CopySourceOperandTag or
|
||||
opcode instanceof MemoryAccessOpcode and tag instanceof AddressOperandTag or
|
||||
opcode instanceof BufferAccessOpcode and tag instanceof BufferSizeOperand or
|
||||
opcode instanceof OpcodeWithCondition and tag instanceof ConditionOperandTag or
|
||||
opcode instanceof Opcode::ReturnValue and tag instanceof ReturnValueOperandTag or
|
||||
opcode instanceof Opcode::ThrowValue and tag instanceof ExceptionOperandTag or
|
||||
opcode instanceof Opcode::UnmodeledUse and tag instanceof UnmodeledUseOperandTag or
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag
|
||||
opcode instanceof Opcode::Call and tag instanceof CallTargetOperandTag or
|
||||
(
|
||||
(opcode instanceof ReadSideEffectOpcode or opcode instanceof MayWriteSideEffectOpcode) and
|
||||
tag instanceof SideEffectOperandTag
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -162,9 +167,9 @@ class Instruction extends Construction::TInstruction {
|
||||
*/
|
||||
final string getOperationString() {
|
||||
if exists(getImmediateString()) then
|
||||
result = opcode.toString() + "[" + getImmediateString() + "]"
|
||||
result = getOperationPrefix() + opcode.toString() + "[" + getImmediateString() + "]"
|
||||
else
|
||||
result = opcode.toString()
|
||||
result = getOperationPrefix() + opcode.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,6 +179,13 @@ class Instruction extends Construction::TInstruction {
|
||||
none()
|
||||
}
|
||||
|
||||
private string getOperationPrefix() {
|
||||
if this instanceof SideEffectInstruction then
|
||||
result = "^"
|
||||
else
|
||||
result = ""
|
||||
}
|
||||
|
||||
private string getResultPrefix() {
|
||||
if resultType instanceof VoidType then
|
||||
result = "v"
|
||||
@@ -1084,6 +1096,9 @@ class SwitchInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that calls a function.
|
||||
*/
|
||||
class CallInstruction extends Instruction {
|
||||
CallInstruction() {
|
||||
opcode instanceof Opcode::Call
|
||||
@@ -1094,6 +1109,116 @@ class CallInstruction extends Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing a side effect of a function call.
|
||||
*/
|
||||
class SideEffectInstruction extends Instruction {
|
||||
SideEffectInstruction() {
|
||||
opcode instanceof SideEffectOpcode
|
||||
}
|
||||
|
||||
final Instruction getPrimaryInstruction() {
|
||||
result = Construction::getPrimaryInstructionForSideEffect(this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be
|
||||
* accessed by that call.
|
||||
*/
|
||||
class CallSideEffectInstruction extends SideEffectInstruction {
|
||||
CallSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof EscapedMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the side effect of a function call on any memory that might be read
|
||||
* by that call.
|
||||
*/
|
||||
class CallReadSideEffectInstruction extends SideEffectInstruction {
|
||||
CallReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::CallReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the read of an indirect buffer parameter within a function call.
|
||||
*/
|
||||
class BufferReadSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferReadSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferReadSideEffect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect parameter within a function call.
|
||||
*/
|
||||
class IndirectWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call. The
|
||||
* entire buffer is overwritten.
|
||||
*/
|
||||
class BufferWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the potential write of an indirect parameter within a function call.
|
||||
* Unlike `IndirectWriteSideEffectInstruction`, the location might not be completely overwritten.
|
||||
* written.
|
||||
*/
|
||||
class IndirectMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
IndirectMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::IndirectMayWriteSideEffect
|
||||
}
|
||||
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction representing the write of an indirect buffer parameter within a function call.
|
||||
* Unlike `BufferWriteSideEffectInstruction`, the buffer might not be completely overwritten.
|
||||
*/
|
||||
class BufferMayWriteSideEffectInstruction extends SideEffectInstruction {
|
||||
BufferMayWriteSideEffectInstruction() {
|
||||
opcode instanceof Opcode::BufferMayWriteSideEffect
|
||||
}
|
||||
override final MemoryAccessKind getResultMemoryAccess() {
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that throws an exception.
|
||||
*/
|
||||
|
||||
@@ -306,6 +306,38 @@ class PositionalArgumentOperand extends ArgumentOperand {
|
||||
}
|
||||
}
|
||||
|
||||
class SideEffectOperand extends NonPhiOperand {
|
||||
SideEffectOperand() {
|
||||
this = TNonPhiOperand(_, sideEffectOperand(), _)
|
||||
}
|
||||
|
||||
override MemoryAccessKind getMemoryAccess() {
|
||||
instr instanceof CallSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof CallReadSideEffectInstruction and
|
||||
result instanceof EscapedMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectReadSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferReadSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectWriteSideEffectInstruction and
|
||||
result instanceof IndirectMemoryAccess
|
||||
or
|
||||
instr instanceof BufferWriteSideEffectInstruction and
|
||||
result instanceof BufferMemoryAccess
|
||||
or
|
||||
instr instanceof IndirectMayWriteSideEffectInstruction and
|
||||
result instanceof IndirectMayMemoryAccess
|
||||
or
|
||||
instr instanceof BufferMayWriteSideEffectInstruction and
|
||||
result instanceof BufferMayMemoryAccess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of a `PhiInstruction`.
|
||||
*/
|
||||
@@ -350,6 +382,7 @@ class PhiOperand extends Operand, TPhiOperand {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An operand that reads a value from memory.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import SSAConstructionInternal
|
||||
import cpp
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.internal.OperandTag
|
||||
private import NewIR
|
||||
|
||||
import Cached
|
||||
@@ -226,6 +227,13 @@ cached private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached Instruction getPrimaryInstructionForSideEffect(Instruction instruction) {
|
||||
exists(OldIR::SideEffectInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
result = getNewInstruction(oldInstruction.getPrimaryInstruction())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssa_variableUpdate(Alias::VirtualVariable vvar,
|
||||
OldIR::Instruction instr, OldIR::IRBlock block, int index) {
|
||||
block.getInstruction(index) = instr and
|
||||
|
||||
@@ -10,6 +10,8 @@ private int getMaxCallArgIndex() {
|
||||
|
||||
private newtype TOperandTag =
|
||||
TAddressOperand() or
|
||||
TBufferSizeOperand() or
|
||||
TSideEffectOperand() or
|
||||
TCopySourceOperand() or
|
||||
TUnaryOperand() or
|
||||
TLeftOperand() or
|
||||
@@ -25,7 +27,7 @@ private newtype TOperandTag =
|
||||
exists(BuiltInOperation op |
|
||||
exists(op.getChild(argIndex))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the kind of operand on an instruction. Each `Instruction` has at
|
||||
@@ -47,7 +49,7 @@ abstract class OperandTag extends TOperandTag {
|
||||
|
||||
/**
|
||||
* The address operand of an instruction that loads or stores a value from
|
||||
* memory (e.g. `Load`, `Store`).
|
||||
* memory (e.g. `Load`, `Store`, `InitializeParameter`, `IndirectReadSideEffect`).
|
||||
*/
|
||||
class AddressOperandTag extends OperandTag, TAddressOperand {
|
||||
override final string toString() {
|
||||
@@ -63,6 +65,37 @@ AddressOperandTag addressOperand() {
|
||||
result = TAddressOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* The buffer size operand of an instruction that represents a read or write of
|
||||
* a buffer.
|
||||
*/
|
||||
class BufferSizeOperand extends OperandTag, TBufferSizeOperand {
|
||||
override final string toString() {
|
||||
result = "BufferSize"
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The operand representing the read side effect of a `SideEffectInstruction`.
|
||||
*/
|
||||
class SideEffectOperandTag extends OperandTag, TSideEffectOperand {
|
||||
override final string toString() {
|
||||
result = "SideEffect"
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 2
|
||||
}
|
||||
}
|
||||
|
||||
SideEffectOperandTag sideEffectOperand() {
|
||||
result = TSideEffectOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* The source value operand of an instruction that copies this value to its
|
||||
* result (e.g. `Copy`, `Load`, `Store`).
|
||||
@@ -73,7 +106,7 @@ class CopySourceOperandTag extends OperandTag, TCopySourceOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 1
|
||||
result = 3
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +123,7 @@ class UnaryOperandTag extends OperandTag, TUnaryOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 2
|
||||
result = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +140,7 @@ class LeftOperandTag extends OperandTag, TLeftOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 3
|
||||
result = 5
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +157,7 @@ class RightOperandTag extends OperandTag, TRightOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 4
|
||||
result = 6
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +174,7 @@ class ReturnValueOperandTag extends OperandTag, TReturnValueOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 5
|
||||
result = 7
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +191,7 @@ class ExceptionOperandTag extends OperandTag, TExceptionOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 6
|
||||
result = 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +208,7 @@ class ConditionOperandTag extends OperandTag, TConditionOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 7
|
||||
result = 9
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +226,7 @@ class UnmodeledUseOperandTag extends OperandTag, TUnmodeledUseOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 8
|
||||
result = 10
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +243,7 @@ class CallTargetOperandTag extends OperandTag, TCallTargetOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 9
|
||||
result = 11
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +273,7 @@ class ThisArgumentOperandTag extends ArgumentOperandTag, TThisArgumentOperand {
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 10
|
||||
result = 12
|
||||
}
|
||||
|
||||
override final string getLabel() {
|
||||
@@ -268,7 +301,7 @@ class PositionalArgumentOperandTag extends ArgumentOperandTag,
|
||||
}
|
||||
|
||||
override final int getSortOrder() {
|
||||
result = 11 + argIndex
|
||||
result = 14 + argIndex
|
||||
}
|
||||
|
||||
final int getArgIndex() {
|
||||
@@ -278,4 +311,4 @@ class PositionalArgumentOperandTag extends ArgumentOperandTag,
|
||||
|
||||
PositionalArgumentOperandTag positionalArgumentOperand(int argIndex) {
|
||||
result = TPositionalArgumentOperand(argIndex)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user