diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index a23fb081afe..4e1dd07a350 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..74c288d3468 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -69,6 +69,7 @@ private predicate operandEscapesDomain(Operand operand) { not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and not operand.getUse() instanceof ReturnValueInstruction and + not operand.getUse() instanceof ReturnIndirectionInstruction and not operand instanceof PhiInputOperand } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index a23fb081afe..4e1dd07a350 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index a23fb081afe..4e1dd07a350 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b36..74c288d3468 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -69,6 +69,7 @@ private predicate operandEscapesDomain(Operand operand) { not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and not operand.getUse() instanceof ReturnValueInstruction and + not operand.getUse() instanceof ReturnIndirectionInstruction and not operand instanceof PhiInputOperand } diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index a7925db2a46..bcaf356c8fe 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -84,7 +84,7 @@ ssa.cpp: # 28| r6_9(int) = Load : &:r6_8, ~m6_0 # 28| r6_10(int) = Add : r6_5, r6_9 # 28| m6_11(int) = Store : &:r6_1, r6_10 -# 13| v6_12(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 13| v6_12(void) = ReturnIndirection : &:r0_5, ~m6_0 # 13| r6_13(glval) = VariableAddress[#return] : # 13| v6_14(void) = ReturnValue : &:r6_13, m6_11 # 13| v6_15(void) = UnmodeledUse : mu* @@ -224,7 +224,7 @@ ssa.cpp: # 71| Block 2 # 71| v2_0(void) = NoOp : -# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~m3_0 # 68| v2_2(void) = ReturnVoid : # 68| v2_3(void) = UnmodeledUse : mu* # 68| v2_4(void) = ExitFunction : @@ -746,7 +746,7 @@ ssa.cpp: # 181| r0_12(int *) = Load : &:r0_11, m0_4 # 181| r0_13(int) = Load : &:r0_12, ~m0_9 # 181| m0_14(int) = Store : &:r0_10, r0_13 -# 179| v0_15(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 179| v0_15(void) = ReturnIndirection : &:r0_5, ~m0_9 # 179| r0_16(glval) = VariableAddress[#return] : # 179| v0_17(void) = ReturnValue : &:r0_16, m0_14 # 179| v0_18(void) = UnmodeledUse : mu* @@ -788,10 +788,10 @@ ssa.cpp: # 186| m0_31(unknown) = InlineAsm : ~mu0_2, 0:r0_27, 1:r0_28, 2:r0_29, 3:r0_30 # 186| m0_32(unknown) = Chi : total:m0_26, partial:m0_31 # 192| v0_33(void) = NoOp : -# 184| v0_34(void) = ReturnIndirection : &:r0_6, ~mu0_2 -# 184| v0_35(void) = ReturnIndirection : &:r0_12, ~mu0_2 -# 184| v0_36(void) = ReturnIndirection : &:r0_18, ~mu0_2 -# 184| v0_37(void) = ReturnIndirection : &:r0_24, ~mu0_2 +# 184| v0_34(void) = ReturnIndirection : &:r0_6, ~m0_32 +# 184| v0_35(void) = ReturnIndirection : &:r0_12, ~m0_32 +# 184| v0_36(void) = ReturnIndirection : &:r0_18, ~m0_32 +# 184| v0_37(void) = ReturnIndirection : &:r0_24, ~m0_32 # 184| v0_38(void) = ReturnVoid : # 184| v0_39(void) = UnmodeledUse : mu* # 184| v0_40(void) = ExitFunction : @@ -846,8 +846,8 @@ ssa.cpp: # 202| r0_45(glval) = VariableAddress[ret] : # 202| r0_46(int) = Load : &:r0_45, m0_43 # 202| m0_47(int) = Store : &:r0_44, r0_46 -# 198| v0_48(void) = ReturnIndirection : &:r0_5, ~mu0_2 -# 198| v0_49(void) = ReturnIndirection : &:r0_10, ~mu0_2 +# 198| v0_48(void) = ReturnIndirection : &:r0_5, ~m0_12 +# 198| v0_49(void) = ReturnIndirection : &:r0_10, ~m0_12 # 198| r0_50(glval) = VariableAddress[#return] : # 198| v0_51(void) = ReturnValue : &:r0_50, m0_47 # 198| v0_52(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 5d7c4447302..2e5973b0680 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -610,6 +610,8 @@ lostReachability | range_analysis.c:371:37:371:39 | Constant: 500 | backEdgeCountMismatch useNotDominatedByDefinition +| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | +| VacuousDestructorCall.cpp:2:29:2:29 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | | VacuousDestructorCall.cpp:4:3:4:3 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | | assume0.cpp:11:2:11:2 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | assume0.cpp:5:6:5:6 | IR: h | void h() | | condition_decls.cpp:16:15:16:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | @@ -662,6 +664,8 @@ useNotDominatedByDefinition | misc.c:174:17:174:22 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:168:6:168:8 | IR: vla | void vla() | | misc.c:174:30:174:35 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:168:6:168:8 | IR: vla | void vla() | | misc.c:219:5:219:26 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | +| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | +| misc.c:219:47:219:48 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:4:220:5 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | ms_try_except.cpp:9:19:9:19 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | IR: ms_try_except | void ms_try_except(int) | | ms_try_except.cpp:19:17:19:17 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | IR: ms_try_except | void ms_try_except(int) | @@ -684,6 +688,8 @@ useNotDominatedByDefinition | stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) | | 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:5:3:8 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | +| 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**) | +| vla.c:3:27:3:30 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:16:5:19 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:22:5:25 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:27:5:30 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 3b386c2c1ec..77754d317d9 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -336,11 +336,12 @@ test.cpp: # 46| m0_46(int) = Store : &:r0_45, r0_44 # 46| valnum = r0_40 # 47| v0_47(void) = NoOp : -# 39| r0_48(glval) = VariableAddress[#return] : +# 39| v0_48(void) = ReturnIndirection : &:r0_9, ~m0_32 +# 39| r0_49(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_49(void) = ReturnValue : &:r0_48 -# 39| v0_50(void) = UnmodeledUse : mu* -# 39| v0_51(void) = ExitFunction : +# 39| v0_50(void) = ReturnValue : &:r0_49 +# 39| v0_51(void) = UnmodeledUse : mu* +# 39| v0_52(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -510,11 +511,13 @@ test.cpp: # 65| valnum = m1_0 # 65| m9_4(unsigned int) = Store : &:r9_1, r9_3 # 65| valnum = m1_0 -# 49| r9_5(glval) = VariableAddress[#return] : +# 49| v9_5(void) = ReturnIndirection : &:r0_5, ~m0_12 +# 49| v9_6(void) = ReturnIndirection : &:r0_10, ~m0_12 +# 49| r9_7(glval) = VariableAddress[#return] : # 49| valnum = r9_1 -# 49| v9_6(void) = ReturnValue : &:r9_5, m9_4 -# 49| v9_7(void) = UnmodeledUse : mu* -# 49| v9_8(void) = ExitFunction : +# 49| v9_8(void) = ReturnValue : &:r9_7, m9_4 +# 49| v9_9(void) = UnmodeledUse : mu* +# 49| v9_10(void) = ExitFunction : # 75| void test04(two_values*) # 75| Block 0 @@ -599,10 +602,13 @@ test.cpp: #-----| Goto -> Block 2 # 82| Block 2 -# 82| v2_0(void) = NoOp : -# 75| v2_1(void) = ReturnVoid : -# 75| v2_2(void) = UnmodeledUse : mu* -# 75| v2_3(void) = ExitFunction : +# 82| m2_0(unknown) = Phi : from 0:~m0_12, from 1:~m1_3 +# 82| valnum = unique +# 82| v2_1(void) = NoOp : +# 75| v2_2(void) = ReturnIndirection : &:r0_5, ~m2_0 +# 75| v2_3(void) = ReturnVoid : +# 75| v2_4(void) = UnmodeledUse : mu* +# 75| v2_5(void) = ExitFunction : # 84| void test05(int, int, void*) # 84| Block 0 @@ -642,46 +648,47 @@ test.cpp: # 88| r0_17(bool) = CompareNE : r0_15, r0_16 # 88| valnum = unique # 88| v0_18(void) = ConditionalBranch : r0_17 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 3 +#-----| True -> Block 2 # 88| Block 1 -# 88| r1_0(glval) = VariableAddress[x] : -# 88| valnum = r0_3 -# 88| r1_1(int) = Load : &:r1_0, m0_4 -# 88| valnum = m0_4 -# 88| r1_2(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 -# 88| m1_3(int) = Store : &:r1_2, r1_1 -# 88| valnum = m0_4 -#-----| Goto -> Block 3 +# 88| m1_0(int) = Phi : from 2:m2_3, from 3:m3_3 +# 88| valnum = m1_0 +# 88| r1_1(glval) = VariableAddress[#temp88:7] : +# 88| valnum = r1_1 +# 88| r1_2(int) = Load : &:r1_1, m1_0 +# 88| valnum = m1_0 +# 88| r1_3(glval) = VariableAddress[v] : +# 88| valnum = r0_12 +# 88| m1_4(int) = Store : &:r1_3, r1_2 +# 88| valnum = m1_0 +# 89| v1_5(void) = NoOp : +# 84| v1_6(void) = ReturnIndirection : &:r0_9, ~m0_11 +# 84| v1_7(void) = ReturnVoid : +# 84| v1_8(void) = UnmodeledUse : mu* +# 84| v1_9(void) = ExitFunction : # 88| Block 2 -# 88| r2_0(glval) = VariableAddress[y] : -# 88| valnum = r0_5 -# 88| r2_1(int) = Load : &:r2_0, m0_6 -# 88| valnum = m0_6 +# 88| r2_0(glval) = VariableAddress[x] : +# 88| valnum = r0_3 +# 88| r2_1(int) = Load : &:r2_0, m0_4 +# 88| valnum = m0_4 # 88| r2_2(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 +# 88| valnum = r1_1 # 88| m2_3(int) = Store : &:r2_2, r2_1 -# 88| valnum = m0_6 -#-----| Goto -> Block 3 +# 88| valnum = m0_4 +#-----| Goto -> Block 1 # 88| Block 3 -# 88| m3_0(int) = Phi : from 1:m1_3, from 2:m2_3 -# 88| valnum = m3_0 -# 88| r3_1(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 -# 88| r3_2(int) = Load : &:r3_1, m3_0 -# 88| valnum = m3_0 -# 88| r3_3(glval) = VariableAddress[v] : -# 88| valnum = r0_12 -# 88| m3_4(int) = Store : &:r3_3, r3_2 -# 88| valnum = m3_0 -# 89| v3_5(void) = NoOp : -# 84| v3_6(void) = ReturnVoid : -# 84| v3_7(void) = UnmodeledUse : mu* -# 84| v3_8(void) = ExitFunction : +# 88| r3_0(glval) = VariableAddress[y] : +# 88| valnum = r0_5 +# 88| r3_1(int) = Load : &:r3_0, m0_6 +# 88| valnum = m0_6 +# 88| r3_2(glval) = VariableAddress[#temp88:7] : +# 88| valnum = r1_1 +# 88| m3_3(int) = Store : &:r3_2, r3_1 +# 88| valnum = m0_6 +#-----| Goto -> Block 1 # 91| int regression_test00() # 91| Block 0 @@ -775,11 +782,12 @@ test.cpp: # 109| valnum = r0_24 # 109| m0_29(int) = Store : &:r0_26, r0_28 # 109| valnum = r0_24 -# 104| r0_30(glval) = VariableAddress[#return] : +# 104| v0_30(void) = ReturnIndirection : &:r0_5, ~m0_7 +# 104| r0_31(glval) = VariableAddress[#return] : # 104| valnum = r0_26 -# 104| v0_31(void) = ReturnValue : &:r0_30, m0_29 -# 104| v0_32(void) = UnmodeledUse : mu* -# 104| v0_33(void) = ExitFunction : +# 104| v0_32(void) = ReturnValue : &:r0_31, m0_29 +# 104| v0_33(void) = UnmodeledUse : mu* +# 104| v0_34(void) = ExitFunction : # 112| void test06() # 112| Block 0 diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index 67507fce11d..713893f52f7 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -9,6 +9,7 @@ private newtype TOpcode = TExitFunction() or TReturnValue() or TReturnVoid() or + TReturnIndirection() or TCopyValue() or TLoad() or TStore() or @@ -202,6 +203,10 @@ module Opcode { final override string toString() { result = "ReturnVoid" } } + class ReturnIndirection extends MemoryAccessOpcode, TReturnIndirection { + final override string toString() { result = "ReturnIndirection" } + } + class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue { final override string toString() { result = "CopyValue" } } 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 f0a9c0e698a..d710515bc06 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 @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll index a23fb081afe..4e1dd07a350 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } 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 f0a9c0e698a..d710515bc06 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 @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll index a23fb081afe..4e1dd07a350 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } }