diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index ef2096e9b392..705a9dcdd0b7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -381,6 +381,14 @@ abstract class TranslatedValueCategoryAdjustment extends TranslatedExpr { final TranslatedCoreExpr getOperand() { result.getExpr() = expr } } +/** + * Holds if `expr` requires an `SehExceptionEdge` to be generated. + */ +private predicate hasSehExceptionEdge(Expr expr) { + expr instanceof PointerDereferenceExpr and + exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) +} + /** * IR translation of an implicit lvalue-to-rvalue conversion on the result of * an expression. @@ -400,7 +408,13 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { tag = LoadTag() and - result = this.getParent().getChildSuccessor(this, kind) + ( + result = this.getParent().getChildSuccessor(this, kind) + or + hasSehExceptionEdge(expr) and + kind instanceof SehExceptionEdge and + result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e)) + ) } override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { @@ -1945,7 +1959,13 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { tag = AssignmentStoreTag() and - result = this.getParent().getChildSuccessor(this, kind) + ( + result = this.getParent().getChildSuccessor(this, kind) + or + hasSehExceptionEdge(expr.getLValue()) and + kind instanceof SehExceptionEdge and + result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e)) + ) } override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index bde0ac736752..d3ef1de1e13a 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -49689,6 +49689,74 @@ try_except.c: # 52| Type = [IntType] int # 52| ValueCategory = prvalue(load) # 54| getStmt(2): [ReturnStmt] return ... +# 56| [TopLevelFunction] void k(int*, int*, int*) +# 56| : +# 56| getParameter(0): [Parameter] b +# 56| Type = [IntPointerType] int * +# 56| getParameter(1): [Parameter] c +# 56| Type = [IntPointerType] int * +# 56| getParameter(2): [Parameter] d +# 56| Type = [IntPointerType] int * +# 56| getEntryPoint(): [BlockStmt] { ... } +# 57| getStmt(0): [DeclStmt] declaration +# 57| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 57| Type = [IntType] int +# 57| getVariable().getInitializer(): [Initializer] initializer for x +# 57| getExpr(): [Literal] 0 +# 57| Type = [IntType] int +# 57| Value = [Literal] 0 +# 57| ValueCategory = prvalue +# 58| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 58| getStmt(): [BlockStmt] { ... } +# 59| getStmt(0): [ExprStmt] ExprStmt +# 59| getExpr(): [AssignExpr] ... = ... +# 59| Type = [IntType] int +# 59| ValueCategory = prvalue +# 59| getLValue(): [VariableAccess] x +# 59| Type = [IntType] int +# 59| ValueCategory = lvalue +# 59| getRValue(): [PointerDereferenceExpr] * ... +# 59| Type = [IntType] int +# 59| ValueCategory = prvalue(load) +# 59| getOperand(): [VariableAccess] b +# 59| Type = [IntPointerType] int * +# 59| ValueCategory = prvalue(load) +# 60| getStmt(1): [ExprStmt] ExprStmt +# 60| getExpr(): [AssignExpr] ... = ... +# 60| Type = [IntType] int +# 60| ValueCategory = prvalue +# 60| getLValue(): [PointerDereferenceExpr] * ... +# 60| Type = [IntType] int +# 60| ValueCategory = lvalue +# 60| getOperand(): [VariableAccess] c +# 60| Type = [IntPointerType] int * +# 60| ValueCategory = prvalue(load) +# 60| getRValue(): [VariableAccess] x +# 60| Type = [IntType] int +# 60| ValueCategory = prvalue(load) +# 61| getStmt(2): [DeclStmt] declaration +# 61| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y +# 61| Type = [IntType] int +# 61| getVariable().getInitializer(): [Initializer] initializer for y +# 61| getExpr(): [PointerDereferenceExpr] * ... +# 61| Type = [IntType] int +# 61| ValueCategory = prvalue(load) +# 61| getOperand(): [VariableAccess] d +# 61| Type = [IntPointerType] int * +# 61| ValueCategory = prvalue(load) +# 63| getCondition(): [Literal] 1 +# 63| Type = [IntType] int +# 63| Value = [Literal] 1 +# 63| ValueCategory = prvalue +# 63| getExcept(): [BlockStmt] { ... } +# 64| getStmt(0): [ExprStmt] ExprStmt +# 64| getExpr(): [FunctionCall] call to sink +# 64| Type = [VoidType] void +# 64| ValueCategory = prvalue +# 64| getArgument(0): [VariableAccess] x +# 64| Type = [IntType] int +# 64| ValueCategory = prvalue(load) +# 66| getStmt(2): [ReturnStmt] return ... try_except.cpp: # 3| [TopLevelFunction] void ProbeFunction() # 3| : diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 4f35e4f62097..850168dd6d52 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39258,6 +39258,105 @@ try_except.c: # 46| Block 7 # 46| v46_10(void) = Unreached : +# 56| void k(int*, int*, int*) +# 56| Block 0 +# 56| v56_1(void) = EnterFunction : +# 56| m56_2(unknown) = AliasedDefinition : +# 56| m56_3(unknown) = InitializeNonLocal : +# 56| m56_4(unknown) = Chi : total:m56_2, partial:m56_3 +# 56| r56_5(glval) = VariableAddress[b] : +# 56| m56_6(int *) = InitializeParameter[b] : &:r56_5 +# 56| r56_7(int *) = Load[b] : &:r56_5, m56_6 +# 56| m56_8(unknown) = InitializeIndirection[b] : &:r56_7 +# 56| r56_9(glval) = VariableAddress[c] : +# 56| m56_10(int *) = InitializeParameter[c] : &:r56_9 +# 56| r56_11(int *) = Load[c] : &:r56_9, m56_10 +# 56| m56_12(unknown) = InitializeIndirection[c] : &:r56_11 +# 56| r56_13(glval) = VariableAddress[d] : +# 56| m56_14(int *) = InitializeParameter[d] : &:r56_13 +# 56| r56_15(int *) = Load[d] : &:r56_13, m56_14 +# 56| m56_16(unknown) = InitializeIndirection[d] : &:r56_15 +# 57| r57_1(glval) = VariableAddress[x] : +# 57| r57_2(int) = Constant[0] : +# 57| m57_3(int) = Store[x] : &:r57_1, r57_2 +# 59| r59_1(glval) = VariableAddress[b] : +# 59| r59_2(int *) = Load[b] : &:r59_1, m56_6 +# 59| r59_3(int) = Load[?] : &:r59_2, ~m56_8 +#-----| Goto -> Block 1 +#-----| SEH Exception -> Block 6 + +# 59| Block 1 +# 59| r59_4(glval) = VariableAddress[x] : +# 59| m59_5(int) = Store[x] : &:r59_4, r59_3 +# 60| r60_1(glval) = VariableAddress[x] : +# 60| r60_2(int) = Load[x] : &:r60_1, m59_5 +# 60| r60_3(glval) = VariableAddress[c] : +# 60| r60_4(int *) = Load[c] : &:r60_3, m56_10 +# 60| r60_5(glval) = CopyValue : r60_4 +# 60| m60_6(int) = Store[?] : &:r60_5, r60_2 +# 60| m60_7(unknown) = Chi : total:m56_12, partial:m60_6 +#-----| Goto -> Block 2 +#-----| SEH Exception -> Block 6 + +# 61| Block 2 +# 61| r61_1(glval) = VariableAddress[y] : +# 61| r61_2(glval) = VariableAddress[d] : +# 61| r61_3(int *) = Load[d] : &:r61_2, m56_14 +# 61| r61_4(int) = Load[?] : &:r61_3, ~m56_16 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 + +# 61| Block 3 +# 61| m61_5(int) = Store[y] : &:r61_1, r61_4 +#-----| Goto -> Block 8 + +# 63| Block 4 +# 63| r63_1(int) = Constant[0] : +# 63| r63_2(bool) = CompareEQ : r63_9, r63_1 +# 63| v63_3(void) = ConditionalBranch : r63_2 +#-----| False -> Block 5 +#-----| True -> Block 9 + +# 63| Block 5 +# 63| r63_4(int) = Constant[1] : +# 63| r63_5(bool) = CompareEQ : r63_9, r63_4 +# 63| v63_6(void) = ConditionalBranch : r63_5 +#-----| False -> Block 9 +#-----| True -> Block 7 + +# 63| Block 6 +# 63| m63_7(unknown) = Phi : from 0:m56_12, from 1:m60_7, from 2:m60_7 +# 63| m63_8(int) = Phi : from 0:m57_3, from 1:m59_5, from 2:m59_5 +# 63| r63_9(int) = Constant[1] : +# 63| r63_10(int) = Constant[-1] : +# 63| r63_11(bool) = CompareEQ : r63_9, r63_10 +# 63| v63_12(void) = ConditionalBranch : r63_11 +#-----| False -> Block 4 +#-----| True -> Block 9 + +# 64| Block 7 +# 64| r64_1(glval) = FunctionAddress[sink] : +# 64| r64_2(glval) = VariableAddress[x] : +# 64| r64_3(int) = Load[x] : &:r64_2, m63_8 +# 64| v64_4(void) = Call[sink] : func:r64_1, 0:r64_3 +# 64| m64_5(unknown) = ^CallSideEffect : ~m56_4 +# 64| m64_6(unknown) = Chi : total:m56_4, partial:m64_5 +#-----| Goto -> Block 8 + +# 66| Block 8 +# 66| m66_1(unknown) = Phi : from 3:m60_7, from 7:m63_7 +# 66| m66_2(unknown) = Phi : from 3:~m56_4, from 7:~m64_6 +# 66| v66_3(void) = NoOp : +# 56| v56_17(void) = ReturnIndirection[b] : &:r56_7, m56_8 +# 56| v56_18(void) = ReturnIndirection[c] : &:r56_11, m66_1 +# 56| v56_19(void) = ReturnIndirection[d] : &:r56_15, m56_16 +# 56| v56_20(void) = ReturnVoid : +# 56| v56_21(void) = AliasedUse : ~m66_2 +# 56| v56_22(void) = ExitFunction : + +# 56| Block 9 +# 56| v56_23(void) = Unreached : + try_except.cpp: # 6| void f_cpp() # 6| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 26b6d8a18170..030db017203f 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37533,6 +37533,101 @@ try_except.c: # 46| v46_9(void) = ReturnVoid : #-----| Goto -> Block 1 +# 56| void k(int*, int*, int*) +# 56| Block 0 +# 56| v56_1(void) = EnterFunction : +# 56| mu56_2(unknown) = AliasedDefinition : +# 56| mu56_3(unknown) = InitializeNonLocal : +# 56| r56_4(glval) = VariableAddress[b] : +# 56| mu56_5(int *) = InitializeParameter[b] : &:r56_4 +# 56| r56_6(int *) = Load[b] : &:r56_4, ~m? +# 56| mu56_7(unknown) = InitializeIndirection[b] : &:r56_6 +# 56| r56_8(glval) = VariableAddress[c] : +# 56| mu56_9(int *) = InitializeParameter[c] : &:r56_8 +# 56| r56_10(int *) = Load[c] : &:r56_8, ~m? +# 56| mu56_11(unknown) = InitializeIndirection[c] : &:r56_10 +# 56| r56_12(glval) = VariableAddress[d] : +# 56| mu56_13(int *) = InitializeParameter[d] : &:r56_12 +# 56| r56_14(int *) = Load[d] : &:r56_12, ~m? +# 56| mu56_15(unknown) = InitializeIndirection[d] : &:r56_14 +# 57| r57_1(glval) = VariableAddress[x] : +# 57| r57_2(int) = Constant[0] : +# 57| mu57_3(int) = Store[x] : &:r57_1, r57_2 +# 59| r59_1(glval) = VariableAddress[b] : +# 59| r59_2(int *) = Load[b] : &:r59_1, ~m? +# 59| r59_3(int) = Load[?] : &:r59_2, ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 8 + +# 56| Block 1 +# 56| v56_16(void) = AliasedUse : ~m? +# 56| v56_17(void) = ExitFunction : + +# 56| Block 2 +# 56| v56_18(void) = Unwind : +#-----| Goto -> Block 1 + +# 59| Block 3 +# 59| r59_4(glval) = VariableAddress[x] : +# 59| mu59_5(int) = Store[x] : &:r59_4, r59_3 +# 60| r60_1(glval) = VariableAddress[x] : +# 60| r60_2(int) = Load[x] : &:r60_1, ~m? +# 60| r60_3(glval) = VariableAddress[c] : +# 60| r60_4(int *) = Load[c] : &:r60_3, ~m? +# 60| r60_5(glval) = CopyValue : r60_4 +# 60| mu60_6(int) = Store[?] : &:r60_5, r60_2 +#-----| Goto -> Block 4 +#-----| SEH Exception -> Block 8 + +# 61| Block 4 +# 61| r61_1(glval) = VariableAddress[y] : +# 61| r61_2(glval) = VariableAddress[d] : +# 61| r61_3(int *) = Load[d] : &:r61_2, ~m? +# 61| r61_4(int) = Load[?] : &:r61_3, ~m? +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 8 + +# 61| Block 5 +# 61| mu61_5(int) = Store[y] : &:r61_1, r61_4 +#-----| Goto -> Block 10 + +# 63| Block 6 +# 63| r63_1(int) = Constant[0] : +# 63| r63_2(bool) = CompareEQ : r63_7, r63_1 +# 63| v63_3(void) = ConditionalBranch : r63_2 +#-----| False -> Block 7 +#-----| True -> Block 2 + +# 63| Block 7 +# 63| r63_4(int) = Constant[1] : +# 63| r63_5(bool) = CompareEQ : r63_7, r63_4 +# 63| v63_6(void) = ConditionalBranch : r63_5 +#-----| True -> Block 9 + +# 63| Block 8 +# 63| r63_7(int) = Constant[1] : +# 63| r63_8(int) = Constant[-1] : +# 63| r63_9(bool) = CompareEQ : r63_7, r63_8 +# 63| v63_10(void) = ConditionalBranch : r63_9 +#-----| False -> Block 6 +#-----| True -> Block 2 + +# 64| Block 9 +# 64| r64_1(glval) = FunctionAddress[sink] : +# 64| r64_2(glval) = VariableAddress[x] : +# 64| r64_3(int) = Load[x] : &:r64_2, ~m? +# 64| v64_4(void) = Call[sink] : func:r64_1, 0:r64_3 +# 64| mu64_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 10 + +# 66| Block 10 +# 66| v66_1(void) = NoOp : +# 56| v56_19(void) = ReturnIndirection[b] : &:r56_6, ~m? +# 56| v56_20(void) = ReturnIndirection[c] : &:r56_10, ~m? +# 56| v56_21(void) = ReturnIndirection[d] : &:r56_14, ~m? +# 56| v56_22(void) = ReturnVoid : +#-----| Goto -> Block 1 + try_except.cpp: # 6| void f_cpp() # 6| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.c b/cpp/ql/test/library-tests/ir/ir/try_except.c index 48f3227bf078..27eb8d24e174 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.c +++ b/cpp/ql/test/library-tests/ir/ir/try_except.c @@ -52,3 +52,15 @@ void j(int b) { sink(x); } } + +void k(int *b, int *c, int *d) { + int x = 0; + __try { + x = *b; + *c = x; + int y = *d; + } + __except (1) { + sink(x); + } +} diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.cpp b/cpp/ql/test/library-tests/ir/ir/try_except.cpp index d1e33de0ba00..3db7128de716 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.cpp +++ b/cpp/ql/test/library-tests/ir/ir/try_except.cpp @@ -49,6 +49,6 @@ void throw_cpp(int b) { } } __except (1) { - sink(x); + sink(x); } }