From c24bceddcd37062f9603f0b9e01f576a06e72b8a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 22 Jan 2020 13:11:42 +0100 Subject: [PATCH] C++: Add ReadSideEffectInstruction to IR There was already a `WriteSideEffectInstruction` class that served as a superclass for all the specific write side effects. This new class serves the same purpose for read side effects. --- .../aliased_ssa/Instruction.qll | 47 ++++++++++++------- .../cpp/ir/implementation/raw/Instruction.qll | 47 ++++++++++++------- .../unaliased_ssa/Instruction.qll | 47 ++++++++++++------- .../ir/implementation/raw/Instruction.qll | 47 ++++++++++++------- .../unaliased_ssa/Instruction.qll | 47 ++++++++++++------- 5 files changed, 145 insertions(+), 90 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index a370888c895..7514f580813 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction { } /** - * An instruction representing the side effect of a function call on any memory that might be read - * by that call. + * An instruction representing the side effect of a function call on any memory + * that might be read by that call. This instruction is emitted instead of + * `CallSideEffectInstruction` when it's certain that the call target cannot + * write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } } +/** + * An instruction representing a read side effect of a function call on a + * specific parameter. + */ +class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { + ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + + /** Gets the operand for the value that will be read from this instruction, if known. */ + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + /** Gets the value that will be read from this instruction, if known. */ + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + /** Gets the operand for the address from which this instruction may read. */ + final AddressOperand getArgumentOperand() { result = getAnOperand() } + + /** Gets the address from which this instruction may read. */ + final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } +} + /** * An instruction representing the read of an indirect parameter within a function call. */ -class IndirectReadSideEffectInstruction extends SideEffectInstruction { +class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends SideEffectInstruction { +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class SizedBufferReadSideEffectInstruction extends SideEffectInstruction { +class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::SizedBufferReadSideEffect } - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** - * An instruction representing a side effect of a function call. + * An instruction representing a write side effect of a function call on a + * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index a370888c895..7514f580813 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction { } /** - * An instruction representing the side effect of a function call on any memory that might be read - * by that call. + * An instruction representing the side effect of a function call on any memory + * that might be read by that call. This instruction is emitted instead of + * `CallSideEffectInstruction` when it's certain that the call target cannot + * write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } } +/** + * An instruction representing a read side effect of a function call on a + * specific parameter. + */ +class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { + ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + + /** Gets the operand for the value that will be read from this instruction, if known. */ + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + /** Gets the value that will be read from this instruction, if known. */ + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + /** Gets the operand for the address from which this instruction may read. */ + final AddressOperand getArgumentOperand() { result = getAnOperand() } + + /** Gets the address from which this instruction may read. */ + final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } +} + /** * An instruction representing the read of an indirect parameter within a function call. */ -class IndirectReadSideEffectInstruction extends SideEffectInstruction { +class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends SideEffectInstruction { +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class SizedBufferReadSideEffectInstruction extends SideEffectInstruction { +class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::SizedBufferReadSideEffect } - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** - * An instruction representing a side effect of a function call. + * An instruction representing a write side effect of a function call on a + * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index a370888c895..7514f580813 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction { } /** - * An instruction representing the side effect of a function call on any memory that might be read - * by that call. + * An instruction representing the side effect of a function call on any memory + * that might be read by that call. This instruction is emitted instead of + * `CallSideEffectInstruction` when it's certain that the call target cannot + * write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } } +/** + * An instruction representing a read side effect of a function call on a + * specific parameter. + */ +class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { + ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + + /** Gets the operand for the value that will be read from this instruction, if known. */ + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + /** Gets the value that will be read from this instruction, if known. */ + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + /** Gets the operand for the address from which this instruction may read. */ + final AddressOperand getArgumentOperand() { result = getAnOperand() } + + /** Gets the address from which this instruction may read. */ + final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } +} + /** * An instruction representing the read of an indirect parameter within a function call. */ -class IndirectReadSideEffectInstruction extends SideEffectInstruction { +class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends SideEffectInstruction { +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class SizedBufferReadSideEffectInstruction extends SideEffectInstruction { +class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::SizedBufferReadSideEffect } - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** - * An instruction representing a side effect of a function call. + * An instruction representing a write side effect of a function call on a + * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index a370888c895..7514f580813 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction { } /** - * An instruction representing the side effect of a function call on any memory that might be read - * by that call. + * An instruction representing the side effect of a function call on any memory + * that might be read by that call. This instruction is emitted instead of + * `CallSideEffectInstruction` when it's certain that the call target cannot + * write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } } +/** + * An instruction representing a read side effect of a function call on a + * specific parameter. + */ +class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { + ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + + /** Gets the operand for the value that will be read from this instruction, if known. */ + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + /** Gets the value that will be read from this instruction, if known. */ + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + /** Gets the operand for the address from which this instruction may read. */ + final AddressOperand getArgumentOperand() { result = getAnOperand() } + + /** Gets the address from which this instruction may read. */ + final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } +} + /** * An instruction representing the read of an indirect parameter within a function call. */ -class IndirectReadSideEffectInstruction extends SideEffectInstruction { +class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends SideEffectInstruction { +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class SizedBufferReadSideEffectInstruction extends SideEffectInstruction { +class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::SizedBufferReadSideEffect } - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** - * An instruction representing a side effect of a function call. + * An instruction representing a write side effect of a function call on a + * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index a370888c895..7514f580813 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction { } /** - * An instruction representing the side effect of a function call on any memory that might be read - * by that call. + * An instruction representing the side effect of a function call on any memory + * that might be read by that call. This instruction is emitted instead of + * `CallSideEffectInstruction` when it's certain that the call target cannot + * write to escaped memory. */ class CallReadSideEffectInstruction extends SideEffectInstruction { CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect } } +/** + * An instruction representing a read side effect of a function call on a + * specific parameter. + */ +class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { + ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode } + + /** Gets the operand for the value that will be read from this instruction, if known. */ + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + /** Gets the value that will be read from this instruction, if known. */ + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + /** Gets the operand for the address from which this instruction may read. */ + final AddressOperand getArgumentOperand() { result = getAnOperand() } + + /** Gets the address from which this instruction may read. */ + final Instruction getArgumentDef() { result = getArgumentOperand().getDef() } +} + /** * An instruction representing the read of an indirect parameter within a function call. */ -class IndirectReadSideEffectInstruction extends SideEffectInstruction { +class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction { IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class BufferReadSideEffectInstruction extends SideEffectInstruction { +class BufferReadSideEffectInstruction extends ReadSideEffectInstruction { BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect } - - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** * An instruction representing the read of an indirect buffer parameter within a function call. */ -class SizedBufferReadSideEffectInstruction extends SideEffectInstruction { +class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction { SizedBufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::SizedBufferReadSideEffect } - Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() } - Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() } - - Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() } } /** - * An instruction representing a side effect of a function call. + * An instruction representing a write side effect of a function call on a + * specific parameter. */ class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction { WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }