From 0038d0f17c9f30fb92d0047a5cf5c3c5effe89ba Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 10 Dec 2024 14:44:58 +0100 Subject: [PATCH 1/7] C++: Deprecate `ThrowingFunction` and no longer use in IR --- .../cpp/ir/implementation/raw/internal/TranslatedCall.qll | 4 ---- cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll | 4 +++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 4f8932c4a289..f34ef0054c26 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -363,14 +363,10 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { } final override predicate mayThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(_) - or expr.getTarget() instanceof AlwaysSehThrowingFunction } final override predicate mustThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(true) - or expr.getTarget() instanceof AlwaysSehThrowingFunction } } diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index cc2948067092..111b99533957 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -12,8 +12,10 @@ import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs /** * A function that is known to raise an exception. + * + * DEPRECATED: use `AlwaysSehThrowingFunction` instead. */ -abstract class ThrowingFunction extends Function { +abstract deprecated class ThrowingFunction extends Function { /** * Holds if this function may throw an exception during evaluation. * If `unconditional` is `true` the function always throws an exception. From 6f41d3c4e316e9e353aeca452dcb25c6f8221f66 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 10 Dec 2024 15:01:07 +0100 Subject: [PATCH 2/7] C++: Use SEH exception edges for functions that unconditionally throw those --- .../raw/internal/TranslatedCall.qll | 26 +++++++++---------- .../raw/internal/TranslatedExpr.qll | 8 +++--- .../raw/internal/TranslatedFunction.qll | 2 +- .../library-tests/ir/ir/aliased_ir.expected | 14 +++++----- .../test/library-tests/ir/ir/raw_ir.expected | 14 +++++----- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index f34ef0054c26..15fa13242f94 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -84,11 +84,10 @@ abstract class TranslatedCall extends TranslatedExpr { this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction() ) else ( - not this.mustThrowException() and + not this.mustThrowException(_) and result = this.getParent().getChildSuccessor(this, kind) or - this.mayThrowException() and - kind instanceof CppExceptionEdge and + this.mayThrowException(kind) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) ) } @@ -117,14 +116,14 @@ abstract class TranslatedCall extends TranslatedExpr { final override Instruction getResult() { result = this.getInstruction(CallTag()) } /** - * Holds if the evaluation of this call may throw an exception. + * Holds if the evaluation of this call may throw an exception of the kind represented by the `ExceptionEdge`. */ - abstract predicate mayThrowException(); + abstract predicate mayThrowException(ExceptionEdge e); /** - * Holds if the evaluation of this call always throws an exception. + * Holds if the evaluation of this call always throws an exception of the kind represented by the `ExceptionEdge`. */ - abstract predicate mustThrowException(); + abstract predicate mustThrowException(ExceptionEdge e); /** * Gets the result type of the call. @@ -332,14 +331,14 @@ class TranslatedExprCall extends TranslatedCallExpr { result = getTranslatedExpr(expr.getExpr().getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { // We assume that a call to a function pointer will not throw an exception. // This is not sound in general, but this will greatly reduce the number of // exceptional edges. none() } - final override predicate mustThrowException() { none() } + final override predicate mustThrowException(ExceptionEdge e) { none() } } /** @@ -362,12 +361,11 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) } - final override predicate mayThrowException() { - expr.getTarget() instanceof AlwaysSehThrowingFunction - } + final override predicate mayThrowException(ExceptionEdge e) { this.mustThrowException(e) } - final override predicate mustThrowException() { - expr.getTarget() instanceof AlwaysSehThrowingFunction + final override predicate mustThrowException(ExceptionEdge e) { + expr.getTarget() instanceof AlwaysSehThrowingFunction and + e instanceof SehExceptionEdge } } 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 f21f44956768..ef2096e9b392 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 @@ -2483,14 +2483,14 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index).getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { // We assume that a call to `new` or `new[]` will never throw. This is not // sound in general, but this will greatly reduce the number of exceptional // edges. none() } - final override predicate mustThrowException() { none() } + final override predicate mustThrowException(ExceptionEdge e) { none() } } TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { @@ -2556,14 +2556,14 @@ class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, Trans result = getTranslatedExpr(expr.getExprWithReuse().getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { // We assume that a call to `delete` or `delete[]` will never throw. This is not // sound in general, but this will greatly reduce the number of exceptional // edges. none() } - final override predicate mustThrowException() { none() } + final override predicate mustThrowException(ExceptionEdge e) { none() } } TranslatedDeleteOrDeleteArrayExpr getTranslatedDeleteOrDeleteArray(DeleteOrDeleteArrayExpr newExpr) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 57f718bcb6ab..83736ae98d04 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -214,7 +214,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction { exists(ThrowExpr throw | throw.getEnclosingFunction() = func) or exists(FunctionCall call | call.getEnclosingFunction() = func | - getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException() + getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException(_) ) ) or 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 fbd0db5e7966..a83adf6e74cc 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -3244,7 +3244,7 @@ ir.c: # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| m25_5(unknown) = ^CallSideEffect : ~m21_4 # 25| m25_6(unknown) = Chi : total:m21_4, partial:m25_5 -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 26| Block 1 # 26| r26_1(int) = Constant[0] : @@ -3291,7 +3291,7 @@ ir.c: # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| m36_4(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4 -#-----| C++ Exception -> Block 4 +#-----| SEH Exception -> Block 4 # 32| Block 1 # 32| v32_5(void) = Unwind : @@ -3326,7 +3326,7 @@ ir.c: # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| m40_4(unknown) = ^CallSideEffect : ~m36_5 # 40| m40_5(unknown) = Chi : total:m36_5, partial:m40_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 32| Block 6 # 32| v32_8(void) = Unreached : @@ -3365,7 +3365,7 @@ ir.c: # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| m62_4(unknown) = ^CallSideEffect : ~m57_4 # 62| m62_5(unknown) = Chi : total:m57_4, partial:m62_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 66| Block 1 # 66| r66_1(int) = Constant[1] : @@ -3387,7 +3387,7 @@ ir.c: # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| m73_4(unknown) = ^CallSideEffect : ~m70_4 # 73| m73_5(unknown) = Chi : total:m70_4, partial:m73_4 -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 70| Block 1 # 70| v70_5(void) = Unwind : @@ -3400,7 +3400,7 @@ ir.c: # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| m76_4(unknown) = ^CallSideEffect : ~m73_5 # 76| m76_5(unknown) = Chi : total:m73_5, partial:m76_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 80| void raise_access_violation() # 80| Block 0 @@ -3413,7 +3413,7 @@ ir.c: # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| m81_4(unknown) = ^CallSideEffect : ~m80_4 # 81| m81_5(unknown) = Chi : total:m80_4, partial:m81_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 80| Block 1 # 80| v80_5(void) = Unwind : 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 978d05d4b165..ecd1c2deaed9 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -3000,7 +3000,7 @@ ir.c: # 25| r25_3(int) = Load[x] : &:r25_2, ~m? # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| mu25_5(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 6 +#-----| SEH Exception -> Block 6 # 21| Block 1 # 21| v21_6(void) = AliasedUse : ~m? @@ -3057,7 +3057,7 @@ ir.c: # 36| r36_2(int) = Constant[0] : # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| mu36_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 5 +#-----| SEH Exception -> Block 5 # 32| Block 1 # 32| v32_4(void) = AliasedUse : ~m? @@ -3093,7 +3093,7 @@ ir.c: # 40| r40_2(int) = Constant[1] : # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| mu40_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 42| Block 7 # 42| v42_1(void) = NoOp : @@ -3138,7 +3138,7 @@ ir.c: # 62| r62_2(int) = Constant[0] : # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| mu62_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 57| Block 1 # 57| v57_4(void) = AliasedUse : ~m? @@ -3165,7 +3165,7 @@ ir.c: # 73| r73_2(int) = Constant[0] : # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| mu73_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 70| Block 1 # 70| v70_4(void) = AliasedUse : ~m? @@ -3180,7 +3180,7 @@ ir.c: # 76| r76_2(int) = Constant[0] : # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| mu76_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 78| Block 4 # 78| v78_1(void) = NoOp : @@ -3196,7 +3196,7 @@ ir.c: # 81| r81_2(int) = Constant[1] : # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| mu81_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 80| Block 1 # 80| v80_4(void) = AliasedUse : ~m? From 400424f13c7bb2e7e1a4f7c058089a237c07beeb Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 13 Dec 2024 10:44:40 +0100 Subject: [PATCH 3/7] C++: Add change note --- cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md diff --git a/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md b/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md new file mode 100644 index 000000000000..9a46cc7da8f2 --- /dev/null +++ b/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `ThrowingFunction` class (`semmle.code.cpp.models.interfaces.Throwing`) has been deprecated. Please use the `AlwaysSehThrowingFunction` class instead. From c7a744776814e767541c8692492854ed5e0129cf Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 10 Dec 2024 16:36:49 +0100 Subject: [PATCH 4/7] C++: Generate an SEH exception edge for each call inside a SEH block --- .../raw/internal/TranslatedCall.qll | 7 +- .../library-tests/ir/ir/aliased_ir.expected | 409 +++++++++++++----- .../ir/ir/raw_consistency.expected | 8 - .../test/library-tests/ir/ir/raw_ir.expected | 211 +++++---- 4 files changed, 433 insertions(+), 202 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 15fa13242f94..a1d76bb64917 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -361,7 +361,12 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) } - final override predicate mayThrowException(ExceptionEdge e) { this.mustThrowException(e) } + final override predicate mayThrowException(ExceptionEdge e) { + this.mustThrowException(e) + or + expr.getEnclosingStmt().getParentStmt*() instanceof MicrosoftTryStmt and + e instanceof SehExceptionEdge + } final override predicate mustThrowException(ExceptionEdge e) { expr.getTarget() instanceof AlwaysSehThrowingFunction and 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 a83adf6e74cc..b52912f783e8 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39018,20 +39018,33 @@ struct_init.cpp: try_except.c: # 6| void f() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| m6_2(unknown) = AliasedDefinition : -# 6| m6_3(unknown) = InitializeNonLocal : -# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 -# 7| r7_1(glval) = VariableAddress[x] : -# 7| m7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 -# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +# 6| v6_1(void) = EnterFunction : +# 6| m6_2(unknown) = AliasedDefinition : +# 6| m6_3(unknown) = InitializeNonLocal : +# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 +# 7| r7_1(glval) = VariableAddress[x] : +# 7| m7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 +# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 5 + +# 6| Block 1 +# 6| m6_5(unknown) = Phi : from 2:~m13_4, from 6:~m11_5 +# 6| v6_6(void) = AliasedUse : ~m6_5 +# 6| v6_7(void) = ExitFunction : + +# 6| Block 2 +# 6| v6_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 10| Block 3 # 10| r10_1(glval) = VariableAddress[y] : # 10| r10_2(int) = Load[y] : &:r10_1, m7_5 # 10| r10_3(glval) = VariableAddress[x] : @@ -39041,13 +39054,32 @@ try_except.c: # 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 # 11| m11_4(unknown) = ^CallSideEffect : ~m9_5 # 11| m11_5(unknown) = Chi : total:m9_5, partial:m11_4 -# 16| v16_1(void) = NoOp : -# 6| v6_5(void) = ReturnVoid : -# 6| v6_6(void) = AliasedUse : ~m11_5 -# 6| v6_7(void) = ExitFunction : +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 5 -# 6| Block 1 -# 6| v6_8(void) = Unreached : +# 13| Block 4 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_5, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 7 +#-----| True -> Block 2 + +# 13| Block 5 +# 13| m13_4(unknown) = Phi : from 0:~m9_5, from 3:~m11_5 +# 13| r13_5(int) = Constant[0] : +# 13| r13_6(int) = Constant[-1] : +# 13| r13_7(bool) = CompareEQ : r13_5, r13_6 +# 13| v13_8(void) = ConditionalBranch : r13_7 +#-----| False -> Block 4 +#-----| True -> Block 7 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_9(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 6| Block 7 +# 6| v6_10(void) = Unreached : # 18| void g() # 18| Block 0 @@ -39065,6 +39097,18 @@ try_except.c: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_5(void) = AliasedUse : ~m26_8 +# 18| v18_6(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_7(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -39074,16 +39118,24 @@ try_except.c: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, m22_4 -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| m26_5(unknown) = ^CallSideEffect : ~m23_5 -# 26| m26_6(unknown) = Chi : total:m23_5, partial:m26_5 -# 28| v28_1(void) = NoOp : -# 18| v18_5(void) = ReturnVoid : -# 18| v18_6(void) = AliasedUse : ~m26_6 -# 18| v18_7(void) = ExitFunction : +#-----| Goto|SEH Exception -> Block 4 + +# 26| Block 4 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| r26_3(glval) = FunctionAddress[sink] : +# 26| r26_4(glval) = VariableAddress[x] : +# 26| r26_5(int) = Load[x] : &:r26_4, m26_2 +# 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 +# 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 +# 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 + +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_8(void) = ReturnVoid : +#-----| Goto -> Block 1 # 32| void h(int) # 32| Block 0 @@ -39101,43 +39153,97 @@ try_except.c: # 35| r35_3(int) = Constant[0] : # 35| r35_4(bool) = CompareNE : r35_2, r35_3 # 35| v35_5(void) = ConditionalBranch : r35_4 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 -# 36| Block 1 +# 32| Block 1 +# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 +# 32| v32_8(void) = AliasedUse : ~m32_7 +# 32| v32_9(void) = ExitFunction : + +# 32| Block 2 +# 32| v32_10(void) = Unwind : +#-----| Goto -> Block 1 + +# 36| Block 3 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 2 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 -# 42| Block 2 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4 -# 42| v42_2(void) = NoOp : -# 32| v32_7(void) = ReturnVoid : -# 32| v32_8(void) = AliasedUse : ~m42_1 -# 32| v32_9(void) = ExitFunction : +# 39| Block 4 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_7, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 5 +#-----| True -> Block 9 + +# 39| Block 5 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_7, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| False -> Block 9 +#-----| True -> Block 7 -# 32| Block 3 -# 32| v32_10(void) = Unreached : +# 39| Block 6 +# 39| r39_7(int) = Constant[1] : +# 39| r39_8(int) = Constant[-1] : +# 39| r39_9(bool) = CompareEQ : r39_7, r39_8 +# 39| v39_10(void) = ConditionalBranch : r39_9 +#-----| False -> Block 4 +#-----| True -> Block 9 + +# 40| Block 7 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, m33_3 +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 +# 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 + +# 42| Block 8 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_11(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 32| Block 9 +# 32| v32_12(void) = Unreached : try_except.cpp: # 6| void f_cpp() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| m6_2(unknown) = AliasedDefinition : -# 6| m6_3(unknown) = InitializeNonLocal : -# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 -# 7| r7_1(glval) = VariableAddress[x] : -# 7| m7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 -# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +# 6| v6_1(void) = EnterFunction : +# 6| m6_2(unknown) = AliasedDefinition : +# 6| m6_3(unknown) = InitializeNonLocal : +# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 +# 7| r7_1(glval) = VariableAddress[x] : +# 7| m7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 +# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 5 + +# 6| Block 1 +# 6| m6_5(unknown) = Phi : from 2:~m13_4, from 6:~m11_5 +# 6| v6_6(void) = AliasedUse : ~m6_5 +# 6| v6_7(void) = ExitFunction : + +# 6| Block 2 +# 6| v6_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 10| Block 3 # 10| r10_1(glval) = VariableAddress[y] : # 10| r10_2(int) = Load[y] : &:r10_1, m7_5 # 10| r10_3(glval) = VariableAddress[x] : @@ -39147,13 +39253,32 @@ try_except.cpp: # 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 # 11| m11_4(unknown) = ^CallSideEffect : ~m9_5 # 11| m11_5(unknown) = Chi : total:m9_5, partial:m11_4 -# 16| v16_1(void) = NoOp : -# 6| v6_5(void) = ReturnVoid : -# 6| v6_6(void) = AliasedUse : ~m11_5 -# 6| v6_7(void) = ExitFunction : +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 5 -# 6| Block 1 -# 6| v6_8(void) = Unreached : +# 13| Block 4 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_5, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 7 +#-----| True -> Block 2 + +# 13| Block 5 +# 13| m13_4(unknown) = Phi : from 0:~m9_5, from 3:~m11_5 +# 13| r13_5(int) = Constant[0] : +# 13| r13_6(int) = Constant[-1] : +# 13| r13_7(bool) = CompareEQ : r13_5, r13_6 +# 13| v13_8(void) = ConditionalBranch : r13_7 +#-----| False -> Block 4 +#-----| True -> Block 7 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_9(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 6| Block 7 +# 6| v6_10(void) = Unreached : # 18| void g_cpp() # 18| Block 0 @@ -39171,6 +39296,18 @@ try_except.cpp: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_5(void) = AliasedUse : ~m26_8 +# 18| v18_6(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_7(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -39180,16 +39317,24 @@ try_except.cpp: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, m22_4 -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| m26_5(unknown) = ^CallSideEffect : ~m23_5 -# 26| m26_6(unknown) = Chi : total:m23_5, partial:m26_5 -# 28| v28_1(void) = NoOp : -# 18| v18_5(void) = ReturnVoid : -# 18| v18_6(void) = AliasedUse : ~m26_6 -# 18| v18_7(void) = ExitFunction : +#-----| Goto|SEH Exception -> Block 4 + +# 26| Block 4 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| r26_3(glval) = FunctionAddress[sink] : +# 26| r26_4(glval) = VariableAddress[x] : +# 26| r26_5(int) = Load[x] : &:r26_4, m26_2 +# 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 +# 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 +# 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 + +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_8(void) = ReturnVoid : +#-----| Goto -> Block 1 # 32| void h_cpp(int) # 32| Block 0 @@ -39207,25 +39352,66 @@ try_except.cpp: # 35| r35_3(int) = Constant[0] : # 35| r35_4(bool) = CompareNE : r35_2, r35_3 # 35| v35_5(void) = ConditionalBranch : r35_4 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 + +# 32| Block 1 +# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 +# 32| v32_8(void) = AliasedUse : ~m32_7 +# 32| v32_9(void) = ExitFunction : -# 36| Block 1 +# 32| Block 2 +# 32| v32_10(void) = Unwind : +#-----| Goto -> Block 1 + +# 36| Block 3 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 2 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 -# 42| Block 2 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4 -# 42| v42_2(void) = NoOp : -# 32| v32_7(void) = ReturnVoid : -# 32| v32_8(void) = AliasedUse : ~m42_1 -# 32| v32_9(void) = ExitFunction : +# 39| Block 4 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_7, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 5 +#-----| True -> Block 9 -# 32| Block 3 -# 32| v32_10(void) = Unreached : +# 39| Block 5 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_7, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| False -> Block 9 +#-----| True -> Block 7 + +# 39| Block 6 +# 39| r39_7(int) = Constant[1] : +# 39| r39_8(int) = Constant[-1] : +# 39| r39_9(bool) = CompareEQ : r39_7, r39_8 +# 39| v39_10(void) = ConditionalBranch : r39_9 +#-----| False -> Block 4 +#-----| True -> Block 9 + +# 40| Block 7 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, m33_3 +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 +# 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 + +# 42| Block 8 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_11(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 32| Block 9 +# 32| v32_12(void) = Unreached : # 44| void throw_cpp(int) # 44| Block 0 @@ -39243,53 +39429,62 @@ try_except.cpp: # 47| r47_3(int) = Constant[0] : # 47| r47_4(bool) = CompareNE : r47_2, r47_3 # 47| v47_5(void) = ConditionalBranch : r47_4 -#-----| False -> Block 6 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 -# 48| Block 1 +# 44| Block 1 +# 44| m44_7(unknown) = Phi : from 2:~m52_6, from 8:~m54_1 +# 44| v44_8(void) = AliasedUse : ~m44_7 +# 44| v44_9(void) = ExitFunction : + +# 44| Block 2 +# 44| v44_10(void) = Unwind : +#-----| Goto -> Block 1 + +# 48| Block 3 # 48| r48_1(glval) = VariableAddress[#throw48:13] : # 48| r48_2(int) = Constant[1] : # 48| m48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 # 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 -#-----| C++ Exception -> Block 4 +#-----| C++ Exception -> Block 6 -# 51| Block 2 +# 51| Block 4 # 51| r51_1(int) = Constant[0] : # 51| r51_2(bool) = CompareEQ : r51_7, r51_1 # 51| v51_3(void) = ConditionalBranch : r51_2 -#-----| False -> Block 3 -#-----| True -> Block 7 +#-----| False -> Block 5 +#-----| True -> Block 9 -# 51| Block 3 +# 51| Block 5 # 51| r51_4(int) = Constant[1] : # 51| r51_5(bool) = CompareEQ : r51_7, r51_4 # 51| v51_6(void) = ConditionalBranch : r51_5 -#-----| False -> Block 7 -#-----| True -> Block 5 +#-----| False -> Block 9 +#-----| True -> Block 7 -# 51| Block 4 +# 51| Block 6 # 51| r51_7(int) = Constant[1] : # 51| r51_8(int) = Constant[-1] : # 51| r51_9(bool) = CompareEQ : r51_7, r51_8 # 51| v51_10(void) = ConditionalBranch : r51_9 -#-----| False -> Block 2 -#-----| True -> Block 7 +#-----| False -> Block 4 +#-----| True -> Block 9 -# 52| Block 5 +# 52| Block 7 # 52| r52_1(glval) = FunctionAddress[sink] : # 52| r52_2(glval) = VariableAddress[x] : # 52| r52_3(int) = Load[x] : &:r52_2, m45_3 # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| m52_5(unknown) = ^CallSideEffect : ~m44_4 # 52| m52_6(unknown) = Chi : total:m44_4, partial:m52_5 -#-----| Goto -> Block 6 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 54| Block 6 -# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 5:~m52_6 -# 54| v54_2(void) = NoOp : -# 44| v44_7(void) = ReturnVoid : -# 44| v44_8(void) = AliasedUse : ~m54_1 -# 44| v44_9(void) = ExitFunction : +# 54| Block 8 +# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 7:~m52_6 +# 54| v54_2(void) = NoOp : +# 44| v44_11(void) = ReturnVoid : +#-----| Goto -> Block 1 -# 44| Block 7 -# 44| v44_10(void) = Unreached : +# 44| Block 9 +# 44| v44_12(void) = Unreached : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index ee6f9f2073a7..e30106d35204 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -21,14 +21,6 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | -| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | -| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) | -| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) | -| try_except.cpp:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:6:6:6:10 | void f_cpp() | void f_cpp() | -| try_except.cpp:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:6:6:6:10 | void f_cpp() | void f_cpp() | -| try_except.cpp:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:32:6:32:10 | void h_cpp(int) | void h_cpp(int) | -| try_except.cpp:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:32:6:32:10 | void h_cpp(int) | void h_cpp(int) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated 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 ecd1c2deaed9..ce9de06c34b9 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37288,27 +37288,20 @@ struct_init.cpp: try_except.c: # 6| void f() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| mu6_2(unknown) = AliasedDefinition : -# 6| mu6_3(unknown) = InitializeNonLocal : -# 7| r7_1(glval) = VariableAddress[x] : -# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| mu9_4(unknown) = ^CallSideEffect : ~m? -# 10| r10_1(glval) = VariableAddress[y] : -# 10| r10_2(int) = Load[y] : &:r10_1, ~m? -# 10| r10_3(glval) = VariableAddress[x] : -# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 -# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : -# 11| r11_2(int) = Constant[0] : -# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 -# 11| mu11_4(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +# 6| v6_1(void) = EnterFunction : +# 6| mu6_2(unknown) = AliasedDefinition : +# 6| mu6_3(unknown) = InitializeNonLocal : +# 7| r7_1(glval) = VariableAddress[x] : +# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| mu9_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 6| Block 1 # 6| v6_4(void) = AliasedUse : ~m? @@ -37318,36 +37311,49 @@ try_except.c: # 6| v6_6(void) = Unwind : #-----| Goto -> Block 1 -# 13| Block 3 +# 10| Block 3 +# 10| r10_1(glval) = VariableAddress[y] : +# 10| r10_2(int) = Load[y] : &:r10_1, ~m? +# 10| r10_3(glval) = VariableAddress[x] : +# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 +# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : +# 11| r11_2(int) = Constant[0] : +# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 +# 11| mu11_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 + +# 13| Block 4 # 13| r13_1(int) = Constant[0] : # 13| r13_2(bool) = CompareEQ : r13_7, r13_1 # 13| v13_3(void) = ConditionalBranch : r13_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 13| Block 4 +# 13| Block 5 # 13| r13_4(int) = Constant[1] : # 13| r13_5(bool) = CompareEQ : r13_7, r13_4 # 13| v13_6(void) = ConditionalBranch : r13_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 13| Block 5 +# 13| Block 6 # 13| r13_7(int) = Constant[0] : # 13| r13_8(int) = Constant[-1] : # 13| r13_9(bool) = CompareEQ : r13_7, r13_8 # 13| v13_10(void) = ConditionalBranch : r13_9 -#-----| False -> Block 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 14| Block 6 +# 14| Block 7 # 14| r14_1(glval) = FunctionAddress[sink] : # 14| r14_2(glval) = VariableAddress[x] : # 14| r14_3(int) = Load[x] : &:r14_2, ~m? # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 16| Block 7 +# 16| Block 8 # 16| v16_1(void) = NoOp : # 6| v6_7(void) = ReturnVoid : #-----| Goto -> Block 1 @@ -37366,6 +37372,18 @@ try_except.c: # 21| r21_2(int) = Constant[0] : # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| mu21_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_4(void) = AliasedUse : ~m? +# 18| v18_5(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_6(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, ~m? # 22| r22_3(glval) = VariableAddress[x] : @@ -37374,21 +37392,20 @@ try_except.c: # 23| r23_2(int) = Constant[0] : # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| mu23_4(unknown) = ^CallSideEffect : ~m? -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, ~m? -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| mu26_5(unknown) = ^CallSideEffect : ~m? -# 28| v28_1(void) = NoOp : -# 18| v18_4(void) = ReturnVoid : -#-----| Goto -> Block 1 +#-----| Goto|SEH Exception -> Block 4 -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m? -# 18| v18_6(void) = ExitFunction : +# 26| Block 4 +# 26| r26_1(glval) = FunctionAddress[sink] : +# 26| r26_2(glval) = VariableAddress[x] : +# 26| r26_3(int) = Load[x] : &:r26_2, ~m? +# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 +# 26| mu26_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 -# 18| Block 2 -# 18| v18_7(void) = Unwind : +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h(int) @@ -37422,6 +37439,7 @@ try_except.c: # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| mu36_3(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 # 39| Block 4 # 39| r39_1(int) = Constant[0] : @@ -37451,6 +37469,7 @@ try_except.c: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37460,27 +37479,20 @@ try_except.c: try_except.cpp: # 6| void f_cpp() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| mu6_2(unknown) = AliasedDefinition : -# 6| mu6_3(unknown) = InitializeNonLocal : -# 7| r7_1(glval) = VariableAddress[x] : -# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| mu9_4(unknown) = ^CallSideEffect : ~m? -# 10| r10_1(glval) = VariableAddress[y] : -# 10| r10_2(int) = Load[y] : &:r10_1, ~m? -# 10| r10_3(glval) = VariableAddress[x] : -# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 -# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : -# 11| r11_2(int) = Constant[0] : -# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 -# 11| mu11_4(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +# 6| v6_1(void) = EnterFunction : +# 6| mu6_2(unknown) = AliasedDefinition : +# 6| mu6_3(unknown) = InitializeNonLocal : +# 7| r7_1(glval) = VariableAddress[x] : +# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| mu9_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 6| Block 1 # 6| v6_4(void) = AliasedUse : ~m? @@ -37490,36 +37502,49 @@ try_except.cpp: # 6| v6_6(void) = Unwind : #-----| Goto -> Block 1 -# 13| Block 3 +# 10| Block 3 +# 10| r10_1(glval) = VariableAddress[y] : +# 10| r10_2(int) = Load[y] : &:r10_1, ~m? +# 10| r10_3(glval) = VariableAddress[x] : +# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 +# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : +# 11| r11_2(int) = Constant[0] : +# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 +# 11| mu11_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 + +# 13| Block 4 # 13| r13_1(int) = Constant[0] : # 13| r13_2(bool) = CompareEQ : r13_7, r13_1 # 13| v13_3(void) = ConditionalBranch : r13_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 13| Block 4 +# 13| Block 5 # 13| r13_4(int) = Constant[1] : # 13| r13_5(bool) = CompareEQ : r13_7, r13_4 # 13| v13_6(void) = ConditionalBranch : r13_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 13| Block 5 +# 13| Block 6 # 13| r13_7(int) = Constant[0] : # 13| r13_8(int) = Constant[-1] : # 13| r13_9(bool) = CompareEQ : r13_7, r13_8 # 13| v13_10(void) = ConditionalBranch : r13_9 -#-----| False -> Block 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 14| Block 6 +# 14| Block 7 # 14| r14_1(glval) = FunctionAddress[sink] : # 14| r14_2(glval) = VariableAddress[x] : # 14| r14_3(int) = Load[x] : &:r14_2, ~m? # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 16| Block 7 +# 16| Block 8 # 16| v16_1(void) = NoOp : # 6| v6_7(void) = ReturnVoid : #-----| Goto -> Block 1 @@ -37538,6 +37563,18 @@ try_except.cpp: # 21| r21_2(int) = Constant[0] : # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| mu21_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_4(void) = AliasedUse : ~m? +# 18| v18_5(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_6(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, ~m? # 22| r22_3(glval) = VariableAddress[x] : @@ -37546,21 +37583,20 @@ try_except.cpp: # 23| r23_2(int) = Constant[0] : # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| mu23_4(unknown) = ^CallSideEffect : ~m? -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, ~m? -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| mu26_5(unknown) = ^CallSideEffect : ~m? -# 28| v28_1(void) = NoOp : -# 18| v18_4(void) = ReturnVoid : -#-----| Goto -> Block 1 +#-----| Goto|SEH Exception -> Block 4 -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m? -# 18| v18_6(void) = ExitFunction : +# 26| Block 4 +# 26| r26_1(glval) = FunctionAddress[sink] : +# 26| r26_2(glval) = VariableAddress[x] : +# 26| r26_3(int) = Load[x] : &:r26_2, ~m? +# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 +# 26| mu26_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 -# 18| Block 2 -# 18| v18_7(void) = Unwind : +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h_cpp(int) @@ -37594,6 +37630,7 @@ try_except.cpp: # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| mu36_3(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 # 39| Block 4 # 39| r39_1(int) = Constant[0] : @@ -37623,6 +37660,7 @@ try_except.cpp: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37690,6 +37728,7 @@ try_except.cpp: # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| mu52_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 54| Block 8 # 54| v54_1(void) = NoOp : From 4a42ca8c69a2c2682456bf143a8b778276d9ec6b Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 13 Jun 2025 20:34:35 +0200 Subject: [PATCH 5/7] C++: Limit SEH exception edges to calls in `__try` blocks --- .../raw/internal/TranslatedCall.qll | 2 +- .../library-tests/ir/ir/aliased_ir.expected | 231 +++++++----------- .../test/library-tests/ir/ir/raw_ir.expected | 21 +- 3 files changed, 96 insertions(+), 158 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index a1d76bb64917..9859f0eab0ae 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -364,7 +364,7 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { final override predicate mayThrowException(ExceptionEdge e) { this.mustThrowException(e) or - expr.getEnclosingStmt().getParentStmt*() instanceof MicrosoftTryStmt and + exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt().getAChild*() = expr) and e instanceof SehExceptionEdge } 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 b52912f783e8..707f81d14385 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39097,18 +39097,10 @@ try_except.c: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 -#-----| Goto -> Block 3 -#-----| SEH Exception -> Block 4 - -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m26_8 -# 18| v18_6(void) = ExitFunction : - -# 18| Block 2 -# 18| v18_7(void) = Unwind : #-----| Goto -> Block 1 +#-----| SEH Exception -> Block 2 -# 22| Block 3 +# 22| Block 1 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -39118,24 +39110,21 @@ try_except.c: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -#-----| Goto|SEH Exception -> Block 4 +#-----| Goto|SEH Exception -> Block 2 -# 26| Block 4 -# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 -# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| Block 2 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 1:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 1:m22_4 # 26| r26_3(glval) = FunctionAddress[sink] : # 26| r26_4(glval) = VariableAddress[x] : # 26| r26_5(int) = Load[x] : &:r26_4, m26_2 # 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 # 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 # 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 -#-----| Goto -> Block 5 -#-----| SEH Exception -> Block 2 - -# 28| Block 5 -# 28| v28_1(void) = NoOp : -# 18| v18_8(void) = ReturnVoid : -#-----| Goto -> Block 1 +# 28| v28_1(void) = NoOp : +# 18| v18_5(void) = ReturnVoid : +# 18| v18_6(void) = AliasedUse : ~m26_8 +# 18| v18_7(void) = ExitFunction : # 32| void h(int) # 32| Block 0 @@ -39153,66 +39142,57 @@ try_except.c: # 35| r35_3(int) = Constant[0] : # 35| r35_4(bool) = CompareNE : r35_2, r35_3 # 35| v35_5(void) = ConditionalBranch : r35_4 -#-----| False -> Block 8 -#-----| True -> Block 3 - -# 32| Block 1 -# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 -# 32| v32_8(void) = AliasedUse : ~m32_7 -# 32| v32_9(void) = ExitFunction : - -# 32| Block 2 -# 32| v32_10(void) = Unwind : -#-----| Goto -> Block 1 +#-----| False -> Block 6 +#-----| True -> Block 1 -# 36| Block 3 +# 36| Block 1 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 8 -#-----| SEH Exception -> Block 6 +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 4 -# 39| Block 4 +# 39| Block 2 # 39| r39_1(int) = Constant[0] : # 39| r39_2(bool) = CompareEQ : r39_7, r39_1 # 39| v39_3(void) = ConditionalBranch : r39_2 -#-----| False -> Block 5 -#-----| True -> Block 9 +#-----| False -> Block 3 +#-----| True -> Block 7 -# 39| Block 5 +# 39| Block 3 # 39| r39_4(int) = Constant[1] : # 39| r39_5(bool) = CompareEQ : r39_7, r39_4 # 39| v39_6(void) = ConditionalBranch : r39_5 -#-----| False -> Block 9 -#-----| True -> Block 7 +#-----| False -> Block 7 +#-----| True -> Block 5 -# 39| Block 6 +# 39| Block 4 # 39| r39_7(int) = Constant[1] : # 39| r39_8(int) = Constant[-1] : # 39| r39_9(bool) = CompareEQ : r39_7, r39_8 # 39| v39_10(void) = ConditionalBranch : r39_9 -#-----| False -> Block 4 -#-----| True -> Block 9 +#-----| False -> Block 2 +#-----| True -> Block 7 -# 40| Block 7 +# 40| Block 5 # 40| r40_1(glval) = FunctionAddress[sink] : # 40| r40_2(glval) = VariableAddress[x] : # 40| r40_3(int) = Load[x] : &:r40_2, m33_3 # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 # 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 -#-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 +#-----| Goto -> Block 6 -# 42| Block 8 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 -# 42| v42_2(void) = NoOp : -# 32| v32_11(void) = ReturnVoid : -#-----| Goto -> Block 1 +# 42| Block 6 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4, from 5:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_7(void) = ReturnVoid : +# 32| v32_8(void) = AliasedUse : ~m42_1 +# 32| v32_9(void) = ExitFunction : -# 32| Block 9 -# 32| v32_12(void) = Unreached : +# 32| Block 7 +# 32| v32_10(void) = Unreached : try_except.cpp: # 6| void f_cpp() @@ -39296,18 +39276,10 @@ try_except.cpp: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 -#-----| Goto -> Block 3 -#-----| SEH Exception -> Block 4 - -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m26_8 -# 18| v18_6(void) = ExitFunction : - -# 18| Block 2 -# 18| v18_7(void) = Unwind : #-----| Goto -> Block 1 +#-----| SEH Exception -> Block 2 -# 22| Block 3 +# 22| Block 1 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -39317,24 +39289,21 @@ try_except.cpp: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -#-----| Goto|SEH Exception -> Block 4 +#-----| Goto|SEH Exception -> Block 2 -# 26| Block 4 -# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 -# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| Block 2 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 1:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 1:m22_4 # 26| r26_3(glval) = FunctionAddress[sink] : # 26| r26_4(glval) = VariableAddress[x] : # 26| r26_5(int) = Load[x] : &:r26_4, m26_2 # 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 # 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 # 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 -#-----| Goto -> Block 5 -#-----| SEH Exception -> Block 2 - -# 28| Block 5 -# 28| v28_1(void) = NoOp : -# 18| v18_8(void) = ReturnVoid : -#-----| Goto -> Block 1 +# 28| v28_1(void) = NoOp : +# 18| v18_5(void) = ReturnVoid : +# 18| v18_6(void) = AliasedUse : ~m26_8 +# 18| v18_7(void) = ExitFunction : # 32| void h_cpp(int) # 32| Block 0 @@ -39352,66 +39321,57 @@ try_except.cpp: # 35| r35_3(int) = Constant[0] : # 35| r35_4(bool) = CompareNE : r35_2, r35_3 # 35| v35_5(void) = ConditionalBranch : r35_4 -#-----| False -> Block 8 -#-----| True -> Block 3 - -# 32| Block 1 -# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 -# 32| v32_8(void) = AliasedUse : ~m32_7 -# 32| v32_9(void) = ExitFunction : - -# 32| Block 2 -# 32| v32_10(void) = Unwind : -#-----| Goto -> Block 1 +#-----| False -> Block 6 +#-----| True -> Block 1 -# 36| Block 3 +# 36| Block 1 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 8 -#-----| SEH Exception -> Block 6 +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 4 -# 39| Block 4 +# 39| Block 2 # 39| r39_1(int) = Constant[0] : # 39| r39_2(bool) = CompareEQ : r39_7, r39_1 # 39| v39_3(void) = ConditionalBranch : r39_2 -#-----| False -> Block 5 -#-----| True -> Block 9 +#-----| False -> Block 3 +#-----| True -> Block 7 -# 39| Block 5 +# 39| Block 3 # 39| r39_4(int) = Constant[1] : # 39| r39_5(bool) = CompareEQ : r39_7, r39_4 # 39| v39_6(void) = ConditionalBranch : r39_5 -#-----| False -> Block 9 -#-----| True -> Block 7 +#-----| False -> Block 7 +#-----| True -> Block 5 -# 39| Block 6 +# 39| Block 4 # 39| r39_7(int) = Constant[1] : # 39| r39_8(int) = Constant[-1] : # 39| r39_9(bool) = CompareEQ : r39_7, r39_8 # 39| v39_10(void) = ConditionalBranch : r39_9 -#-----| False -> Block 4 -#-----| True -> Block 9 +#-----| False -> Block 2 +#-----| True -> Block 7 -# 40| Block 7 +# 40| Block 5 # 40| r40_1(glval) = FunctionAddress[sink] : # 40| r40_2(glval) = VariableAddress[x] : # 40| r40_3(int) = Load[x] : &:r40_2, m33_3 # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 # 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 -#-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 +#-----| Goto -> Block 6 -# 42| Block 8 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 -# 42| v42_2(void) = NoOp : -# 32| v32_11(void) = ReturnVoid : -#-----| Goto -> Block 1 +# 42| Block 6 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4, from 5:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_7(void) = ReturnVoid : +# 32| v32_8(void) = AliasedUse : ~m42_1 +# 32| v32_9(void) = ExitFunction : -# 32| Block 9 -# 32| v32_12(void) = Unreached : +# 32| Block 7 +# 32| v32_10(void) = Unreached : # 44| void throw_cpp(int) # 44| Block 0 @@ -39429,62 +39389,53 @@ try_except.cpp: # 47| r47_3(int) = Constant[0] : # 47| r47_4(bool) = CompareNE : r47_2, r47_3 # 47| v47_5(void) = ConditionalBranch : r47_4 -#-----| False -> Block 8 -#-----| True -> Block 3 - -# 44| Block 1 -# 44| m44_7(unknown) = Phi : from 2:~m52_6, from 8:~m54_1 -# 44| v44_8(void) = AliasedUse : ~m44_7 -# 44| v44_9(void) = ExitFunction : - -# 44| Block 2 -# 44| v44_10(void) = Unwind : -#-----| Goto -> Block 1 +#-----| False -> Block 6 +#-----| True -> Block 1 -# 48| Block 3 +# 48| Block 1 # 48| r48_1(glval) = VariableAddress[#throw48:13] : # 48| r48_2(int) = Constant[1] : # 48| m48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 # 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 -#-----| C++ Exception -> Block 6 +#-----| C++ Exception -> Block 4 -# 51| Block 4 +# 51| Block 2 # 51| r51_1(int) = Constant[0] : # 51| r51_2(bool) = CompareEQ : r51_7, r51_1 # 51| v51_3(void) = ConditionalBranch : r51_2 -#-----| False -> Block 5 -#-----| True -> Block 9 +#-----| False -> Block 3 +#-----| True -> Block 7 -# 51| Block 5 +# 51| Block 3 # 51| r51_4(int) = Constant[1] : # 51| r51_5(bool) = CompareEQ : r51_7, r51_4 # 51| v51_6(void) = ConditionalBranch : r51_5 -#-----| False -> Block 9 -#-----| True -> Block 7 +#-----| False -> Block 7 +#-----| True -> Block 5 -# 51| Block 6 +# 51| Block 4 # 51| r51_7(int) = Constant[1] : # 51| r51_8(int) = Constant[-1] : # 51| r51_9(bool) = CompareEQ : r51_7, r51_8 # 51| v51_10(void) = ConditionalBranch : r51_9 -#-----| False -> Block 4 -#-----| True -> Block 9 +#-----| False -> Block 2 +#-----| True -> Block 7 -# 52| Block 7 +# 52| Block 5 # 52| r52_1(glval) = FunctionAddress[sink] : # 52| r52_2(glval) = VariableAddress[x] : # 52| r52_3(int) = Load[x] : &:r52_2, m45_3 # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| m52_5(unknown) = ^CallSideEffect : ~m44_4 # 52| m52_6(unknown) = Chi : total:m44_4, partial:m52_5 -#-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 +#-----| Goto -> Block 6 -# 54| Block 8 -# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 7:~m52_6 -# 54| v54_2(void) = NoOp : -# 44| v44_11(void) = ReturnVoid : -#-----| Goto -> Block 1 +# 54| Block 6 +# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 5:~m52_6 +# 54| v54_2(void) = NoOp : +# 44| v44_7(void) = ReturnVoid : +# 44| v44_8(void) = AliasedUse : ~m54_1 +# 44| v44_9(void) = ExitFunction : -# 44| Block 9 -# 44| v44_12(void) = Unreached : +# 44| Block 7 +# 44| v44_10(void) = Unreached : 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 ce9de06c34b9..dec67c41f717 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37351,7 +37351,6 @@ try_except.c: # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 # 16| Block 8 # 16| v16_1(void) = NoOp : @@ -37400,12 +37399,8 @@ try_except.c: # 26| r26_3(int) = Load[x] : &:r26_2, ~m? # 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 # 26| mu26_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 5 -#-----| SEH Exception -> Block 2 - -# 28| Block 5 -# 28| v28_1(void) = NoOp : -# 18| v18_7(void) = ReturnVoid : +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h(int) @@ -37469,7 +37464,6 @@ try_except.c: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37542,7 +37536,6 @@ try_except.cpp: # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 # 16| Block 8 # 16| v16_1(void) = NoOp : @@ -37591,12 +37584,8 @@ try_except.cpp: # 26| r26_3(int) = Load[x] : &:r26_2, ~m? # 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 # 26| mu26_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 5 -#-----| SEH Exception -> Block 2 - -# 28| Block 5 -# 28| v28_1(void) = NoOp : -# 18| v18_7(void) = ReturnVoid : +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h_cpp(int) @@ -37660,7 +37649,6 @@ try_except.cpp: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37728,7 +37716,6 @@ try_except.cpp: # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| mu52_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 -#-----| SEH Exception -> Block 2 # 54| Block 8 # 54| v54_1(void) = NoOp : From 815ae37a7e3934905a0dccd78fc21eb8f7d14e3c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Sat, 14 Jun 2025 00:05:00 +0200 Subject: [PATCH 6/7] C++: Add test case with call in initialization Fix formatting while here. --- .../library-tests/ir/ir/PrintAST.expected | 37 ++++++++++ .../library-tests/ir/ir/aliased_ir.expected | 33 +++++++-- .../ir/ir/raw_consistency.expected | 2 + .../test/library-tests/ir/ir/raw_ir.expected | 67 +++++++++++++++++-- cpp/ql/test/library-tests/ir/ir/try_except.c | 28 +++++--- .../test/library-tests/ir/ir/try_except.cpp | 28 ++++---- 6 files changed, 165 insertions(+), 30 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index b9ffaf71656b..bde0ac736752 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -49652,6 +49652,43 @@ try_except.c: # 40| Type = [IntType] int # 40| ValueCategory = prvalue(load) # 42| getStmt(2): [ReturnStmt] return ... +# 44| [TopLevelFunction] int i() +# 44| : +# 46| [TopLevelFunction] void j(int) +# 46| : +# 46| getParameter(0): [Parameter] b +# 46| Type = [IntType] int +# 46| getEntryPoint(): [BlockStmt] { ... } +# 47| getStmt(0): [DeclStmt] declaration +# 47| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 47| Type = [IntType] int +# 47| getVariable().getInitializer(): [Initializer] initializer for x +# 47| getExpr(): [Literal] 0 +# 47| Type = [IntType] int +# 47| Value = [Literal] 0 +# 47| ValueCategory = prvalue +# 48| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 48| getStmt(): [BlockStmt] { ... } +# 49| getStmt(0): [DeclStmt] declaration +# 49| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y +# 49| Type = [IntType] int +# 49| getVariable().getInitializer(): [Initializer] initializer for y +# 49| getExpr(): [FunctionCall] call to i +# 49| Type = [IntType] int +# 49| ValueCategory = prvalue +# 51| getCondition(): [Literal] 1 +# 51| Type = [IntType] int +# 51| Value = [Literal] 1 +# 51| ValueCategory = prvalue +# 51| getExcept(): [BlockStmt] { ... } +# 52| getStmt(0): [ExprStmt] ExprStmt +# 52| getExpr(): [FunctionCall] call to sink +# 52| Type = [VoidType] void +# 52| ValueCategory = prvalue +# 52| getArgument(0): [VariableAccess] x +# 52| Type = [IntType] int +# 52| ValueCategory = prvalue(load) +# 54| 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 707f81d14385..3062676daa19 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39194,6 +39194,31 @@ try_except.c: # 32| Block 7 # 32| v32_10(void) = Unreached : +# 46| void j(int) +# 46| Block 0 +# 46| v46_1(void) = EnterFunction : +# 46| m46_2(unknown) = AliasedDefinition : +# 46| m46_3(unknown) = InitializeNonLocal : +# 46| m46_4(unknown) = Chi : total:m46_2, partial:m46_3 +# 46| r46_5(glval) = VariableAddress[b] : +# 46| m46_6(int) = InitializeParameter[b] : &:r46_5 +# 47| r47_1(glval) = VariableAddress[x] : +# 47| r47_2(int) = Constant[0] : +# 47| m47_3(int) = Store[x] : &:r47_1, r47_2 +# 49| r49_1(glval) = VariableAddress[y] : +# 49| r49_2(glval) = FunctionAddress[i] : +# 49| r49_3(int) = Call[i] : func:r49_2 +# 49| m49_4(unknown) = ^CallSideEffect : ~m46_4 +# 49| m49_5(unknown) = Chi : total:m46_4, partial:m49_4 +# 49| m49_6(int) = Store[y] : &:r49_1, r49_3 +# 54| v54_1(void) = NoOp : +# 46| v46_7(void) = ReturnVoid : +# 46| v46_8(void) = AliasedUse : ~m49_5 +# 46| v46_9(void) = ExitFunction : + +# 46| Block 1 +# 46| v46_10(void) = Unreached : + try_except.cpp: # 6| void f_cpp() # 6| Block 0 @@ -39393,10 +39418,10 @@ try_except.cpp: #-----| True -> Block 1 # 48| Block 1 -# 48| r48_1(glval) = VariableAddress[#throw48:13] : -# 48| r48_2(int) = Constant[1] : -# 48| m48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 -# 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 +# 48| r48_1(glval) = VariableAddress[#throw48:7] : +# 48| r48_2(int) = Constant[1] : +# 48| m48_3(int) = Store[#throw48:7] : &:r48_1, r48_2 +# 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 #-----| C++ Exception -> Block 4 # 51| Block 2 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index e30106d35204..7c4038e8ef4d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -21,6 +21,8 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | +| try_except.c:51:13:51:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:46:6:46:6 | void j(int) | void j(int) | +| try_except.c:51:13:51:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:46:6:46:6 | void j(int) | void j(int) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated 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 dec67c41f717..6e1bd39b20a3 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37470,6 +37470,65 @@ try_except.c: # 32| v32_9(void) = ReturnVoid : #-----| Goto -> Block 1 +# 46| void j(int) +# 46| Block 0 +# 46| v46_1(void) = EnterFunction : +# 46| mu46_2(unknown) = AliasedDefinition : +# 46| mu46_3(unknown) = InitializeNonLocal : +# 46| r46_4(glval) = VariableAddress[b] : +# 46| mu46_5(int) = InitializeParameter[b] : &:r46_4 +# 47| r47_1(glval) = VariableAddress[x] : +# 47| r47_2(int) = Constant[0] : +# 47| mu47_3(int) = Store[x] : &:r47_1, r47_2 +# 49| r49_1(glval) = VariableAddress[y] : +# 49| r49_2(glval) = FunctionAddress[i] : +# 49| r49_3(int) = Call[i] : func:r49_2 +# 49| mu49_4(unknown) = ^CallSideEffect : ~m? +# 49| mu49_5(int) = Store[y] : &:r49_1, r49_3 +#-----| Goto -> Block 7 + +# 46| Block 1 +# 46| v46_6(void) = AliasedUse : ~m? +# 46| v46_7(void) = ExitFunction : + +# 46| Block 2 +# 46| v46_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 51| Block 3 +# 51| r51_1(int) = Constant[0] : +# 51| r51_2(bool) = CompareEQ : r51_7, r51_1 +# 51| v51_3(void) = ConditionalBranch : r51_2 +#-----| False -> Block 4 +#-----| True -> Block 2 + +# 51| Block 4 +# 51| r51_4(int) = Constant[1] : +# 51| r51_5(bool) = CompareEQ : r51_7, r51_4 +# 51| v51_6(void) = ConditionalBranch : r51_5 +#-----| True -> Block 6 + +# 51| Block 5 +# 51| r51_7(int) = Constant[1] : +# 51| r51_8(int) = Constant[-1] : +# 51| r51_9(bool) = CompareEQ : r51_7, r51_8 +# 51| v51_10(void) = ConditionalBranch : r51_9 +#-----| False -> Block 3 +#-----| True -> Block 2 + +# 52| Block 6 +# 52| r52_1(glval) = FunctionAddress[sink] : +# 52| r52_2(glval) = VariableAddress[x] : +# 52| r52_3(int) = Load[x] : &:r52_2, ~m? +# 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 +# 52| mu52_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 7 + +# 54| Block 7 +# 54| v54_1(void) = NoOp : +# 46| v46_9(void) = ReturnVoid : +#-----| Goto -> Block 1 + try_except.cpp: # 6| void f_cpp() # 6| Block 0 @@ -37682,10 +37741,10 @@ try_except.cpp: #-----| Goto -> Block 1 # 48| Block 3 -# 48| r48_1(glval) = VariableAddress[#throw48:13] : -# 48| r48_2(int) = Constant[1] : -# 48| mu48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 -# 48| v48_4(void) = ThrowValue : &:r48_1, ~m? +# 48| r48_1(glval) = VariableAddress[#throw48:7] : +# 48| r48_2(int) = Constant[1] : +# 48| mu48_3(int) = Store[#throw48:7] : &:r48_1, r48_2 +# 48| v48_4(void) = ThrowValue : &:r48_1, ~m? #-----| C++ Exception -> Block 6 # 51| Block 4 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 410068dae5ea..48f3227bf078 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.c +++ b/cpp/ql/test/library-tests/ir/ir/try_except.c @@ -31,12 +31,24 @@ void AfxThrowMemoryException(); void h(int b) { int x = 0; - __try { - if (b) { - AfxThrowMemoryException(); - } - } - __except (1) { - sink(x); + __try { + if (b) { + AfxThrowMemoryException(); } -} \ No newline at end of file + } + __except (1) { + sink(x); + } +} + +int i(); + +void j(int b) { + int x = 0; + __try { + int y = i(); + } + __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 9bf297263b75..d1e33de0ba00 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.cpp +++ b/cpp/ql/test/library-tests/ir/ir/try_except.cpp @@ -31,24 +31,24 @@ void AfxThrowMemoryException(); void h_cpp(int b) { int x = 0; - __try { - if (b) { - AfxThrowMemoryException(); - } - } - __except (1) { - sink(x); + __try { + if (b) { + AfxThrowMemoryException(); } + } + __except (1) { + sink(x); + } } void throw_cpp(int b) { int x = 0; - __try { - if (b) { - throw 1; - } - } - __except (1) { - sink(x); + __try { + if (b) { + throw 1; } + } + __except (1) { + sink(x); + } } From 1b2813dcf6c8ed158b484c58427dd935f588da69 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Sat, 14 Jun 2025 00:16:47 +0200 Subject: [PATCH 7/7] C++: Also generate an SEH edge for calls in initializers --- .../raw/internal/TranslatedCall.qll | 2 +- .../library-tests/ir/ir/aliased_ir.expected | 51 ++++++++++++++++--- .../ir/ir/raw_consistency.expected | 2 - .../test/library-tests/ir/ir/raw_ir.expected | 26 ++++++---- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 9859f0eab0ae..db46f6807cdb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -364,7 +364,7 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { final override predicate mayThrowException(ExceptionEdge e) { this.mustThrowException(e) or - exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt().getAChild*() = expr) and + exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) and e instanceof SehExceptionEdge } 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 3062676daa19..4f35e4f62097 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39210,13 +39210,52 @@ try_except.c: # 49| r49_3(int) = Call[i] : func:r49_2 # 49| m49_4(unknown) = ^CallSideEffect : ~m46_4 # 49| m49_5(unknown) = Chi : total:m46_4, partial:m49_4 -# 49| m49_6(int) = Store[y] : &:r49_1, r49_3 -# 54| v54_1(void) = NoOp : -# 46| v46_7(void) = ReturnVoid : -# 46| v46_8(void) = AliasedUse : ~m49_5 -# 46| v46_9(void) = ExitFunction : +#-----| Goto -> Block 1 +#-----| SEH Exception -> Block 4 + +# 49| Block 1 +# 49| m49_6(int) = Store[y] : &:r49_1, r49_3 +#-----| Goto -> Block 6 + +# 51| Block 2 +# 51| r51_1(int) = Constant[0] : +# 51| r51_2(bool) = CompareEQ : r51_7, r51_1 +# 51| v51_3(void) = ConditionalBranch : r51_2 +#-----| False -> Block 3 +#-----| True -> Block 7 + +# 51| Block 3 +# 51| r51_4(int) = Constant[1] : +# 51| r51_5(bool) = CompareEQ : r51_7, r51_4 +# 51| v51_6(void) = ConditionalBranch : r51_5 +#-----| False -> Block 7 +#-----| True -> Block 5 + +# 51| Block 4 +# 51| r51_7(int) = Constant[1] : +# 51| r51_8(int) = Constant[-1] : +# 51| r51_9(bool) = CompareEQ : r51_7, r51_8 +# 51| v51_10(void) = ConditionalBranch : r51_9 +#-----| False -> Block 2 +#-----| True -> Block 7 + +# 52| Block 5 +# 52| r52_1(glval) = FunctionAddress[sink] : +# 52| r52_2(glval) = VariableAddress[x] : +# 52| r52_3(int) = Load[x] : &:r52_2, m47_3 +# 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 +# 52| m52_5(unknown) = ^CallSideEffect : ~m49_5 +# 52| m52_6(unknown) = Chi : total:m49_5, partial:m52_5 +#-----| Goto -> Block 6 + +# 54| Block 6 +# 54| m54_1(unknown) = Phi : from 1:~m49_5, from 5:~m52_6 +# 54| v54_2(void) = NoOp : +# 46| v46_7(void) = ReturnVoid : +# 46| v46_8(void) = AliasedUse : ~m54_1 +# 46| v46_9(void) = ExitFunction : -# 46| Block 1 +# 46| Block 7 # 46| v46_10(void) = Unreached : try_except.cpp: diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index 7c4038e8ef4d..e30106d35204 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -21,8 +21,6 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| try_except.c:51:13:51:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:46:6:46:6 | void j(int) | void j(int) | -| try_except.c:51:13:51:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:46:6:46:6 | void j(int) | void j(int) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated 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 6e1bd39b20a3..26b6d8a18170 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37484,8 +37484,8 @@ try_except.c: # 49| r49_2(glval) = FunctionAddress[i] : # 49| r49_3(int) = Call[i] : func:r49_2 # 49| mu49_4(unknown) = ^CallSideEffect : ~m? -# 49| mu49_5(int) = Store[y] : &:r49_1, r49_3 -#-----| Goto -> Block 7 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 46| Block 1 # 46| v46_6(void) = AliasedUse : ~m? @@ -37495,36 +37495,40 @@ try_except.c: # 46| v46_8(void) = Unwind : #-----| Goto -> Block 1 -# 51| Block 3 +# 49| Block 3 +# 49| mu49_5(int) = Store[y] : &:r49_1, r49_3 +#-----| Goto -> Block 8 + +# 51| Block 4 # 51| r51_1(int) = Constant[0] : # 51| r51_2(bool) = CompareEQ : r51_7, r51_1 # 51| v51_3(void) = ConditionalBranch : r51_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 51| Block 4 +# 51| Block 5 # 51| r51_4(int) = Constant[1] : # 51| r51_5(bool) = CompareEQ : r51_7, r51_4 # 51| v51_6(void) = ConditionalBranch : r51_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 51| Block 5 +# 51| Block 6 # 51| r51_7(int) = Constant[1] : # 51| r51_8(int) = Constant[-1] : # 51| r51_9(bool) = CompareEQ : r51_7, r51_8 # 51| v51_10(void) = ConditionalBranch : r51_9 -#-----| False -> Block 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 52| Block 6 +# 52| Block 7 # 52| r52_1(glval) = FunctionAddress[sink] : # 52| r52_2(glval) = VariableAddress[x] : # 52| r52_3(int) = Load[x] : &:r52_2, ~m? # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| mu52_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +#-----| Goto -> Block 8 -# 54| Block 7 +# 54| Block 8 # 54| v54_1(void) = NoOp : # 46| v46_9(void) = ReturnVoid : #-----| Goto -> Block 1