From 67d623fb06a79d3c299baed7a869ca262cd3d24d Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 13 Jun 2025 21:33:04 +0200 Subject: [PATCH 1/4] C++: Add `__try` with load test case Fix some formatting while here. --- .../library-tests/ir/ir/PrintAST.expected | 72 ++++++++++++++ .../library-tests/ir/ir/aliased_ir.expected | 77 +++++++++++++++ .../ir/ir/raw_consistency.expected | 2 + .../test/library-tests/ir/ir/raw_ir.expected | 93 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ir/try_except.c | 12 +++ .../test/library-tests/ir/ir/try_except.cpp | 2 +- 6 files changed, 257 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index bde0ac736752..998dc4862892 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -49689,6 +49689,78 @@ try_except.c: # 52| Type = [IntType] int # 52| ValueCategory = prvalue(load) # 54| getStmt(2): [ReturnStmt] return ... +# 56| [TopLevelFunction] void k(int*, int*, 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| getParameter(3): [Parameter] e +# 56| Type = [IntPointerType] int * +# 56| getParameter(4): [Parameter] f +# 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..ca4ba7385f88 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,7 @@ try_except.c: # 32| Block 7 # 32| v32_10(void) = Unreached : +<<<<<<< HEAD # 46| void j(int) # 46| Block 0 # 46| v46_1(void) = EnterFunction : @@ -39257,6 +39258,82 @@ try_except.c: # 46| Block 7 # 46| v46_10(void) = Unreached : +======= +# 44| void i(int*, int*, int*, int*, int*) +# 44| Block 0 +# 44| v44_1(void) = EnterFunction : +# 44| m44_2(unknown) = AliasedDefinition : +# 44| m44_3(unknown) = InitializeNonLocal : +# 44| m44_4(unknown) = Chi : total:m44_2, partial:m44_3 +# 44| r44_5(glval) = VariableAddress[b] : +# 44| m44_6(int *) = InitializeParameter[b] : &:r44_5 +# 44| r44_7(int *) = Load[b] : &:r44_5, m44_6 +# 44| m44_8(unknown) = InitializeIndirection[b] : &:r44_7 +# 44| r44_9(glval) = VariableAddress[c] : +# 44| m44_10(int *) = InitializeParameter[c] : &:r44_9 +# 44| r44_11(int *) = Load[c] : &:r44_9, m44_10 +# 44| m44_12(unknown) = InitializeIndirection[c] : &:r44_11 +# 44| r44_13(glval) = VariableAddress[d] : +# 44| m44_14(int *) = InitializeParameter[d] : &:r44_13 +# 44| r44_15(int *) = Load[d] : &:r44_13, m44_14 +# 44| m44_16(unknown) = InitializeIndirection[d] : &:r44_15 +# 44| r44_17(glval) = VariableAddress[e] : +# 44| m44_18(int *) = InitializeParameter[e] : &:r44_17 +# 44| r44_19(int *) = Load[e] : &:r44_17, m44_18 +# 44| m44_20(unknown) = InitializeIndirection[e] : &:r44_19 +# 44| r44_21(glval) = VariableAddress[f] : +# 44| m44_22(int *) = InitializeParameter[f] : &:r44_21 +# 44| r44_23(int *) = Load[f] : &:r44_21, m44_22 +# 44| m44_24(unknown) = InitializeIndirection[f] : &:r44_23 +# 45| r45_1(glval) = VariableAddress[x] : +# 45| r45_2(int) = Constant[0] : +# 45| m45_3(int) = Store[x] : &:r45_1, r45_2 +# 47| r47_1(glval) = VariableAddress[b] : +# 47| r47_2(int *) = Load[b] : &:r47_1, m44_6 +# 47| r47_3(int) = Load[?] : &:r47_2, ~m44_8 +# 47| r47_4(glval) = VariableAddress[x] : +# 47| m47_5(int) = Store[x] : &:r47_4, r47_3 +# 48| r48_1(glval) = VariableAddress[x] : +# 48| r48_2(int) = Load[x] : &:r48_1, m47_5 +# 48| r48_3(glval) = VariableAddress[c] : +# 48| r48_4(int *) = Load[c] : &:r48_3, m44_10 +# 48| r48_5(glval) = CopyValue : r48_4 +# 48| m48_6(int) = Store[?] : &:r48_5, r48_2 +# 48| m48_7(unknown) = Chi : total:m44_12, partial:m48_6 +# 49| r49_1(glval) = VariableAddress[y] : +# 49| r49_2(glval) = VariableAddress[d] : +# 49| r49_3(int *) = Load[d] : &:r49_2, m44_14 +# 49| r49_4(int) = Load[?] : &:r49_3, ~m44_16 +# 49| m49_5(int) = Store[y] : &:r49_1, r49_4 +# 50| r50_1(glval) = VariableAddress[x] : +# 50| m50_2(int[2]) = Uninitialized[x] : &:r50_1 +# 50| r50_3(int) = Constant[0] : +# 50| r50_4(glval) = PointerAdd[4] : r50_1, r50_3 +# 50| r50_5(glval) = VariableAddress[e] : +# 50| r50_6(int *) = Load[e] : &:r50_5, m44_18 +# 50| r50_7(int) = Load[?] : &:r50_6, ~m44_20 +# 50| m50_8(int) = Store[?] : &:r50_4, r50_7 +# 50| m50_9(int[2]) = Chi : total:m50_2, partial:m50_8 +# 50| r50_10(int) = Constant[1] : +# 50| r50_11(glval) = PointerAdd[4] : r50_1, r50_10 +# 50| r50_12(glval) = VariableAddress[f] : +# 50| r50_13(int *) = Load[f] : &:r50_12, m44_22 +# 50| r50_14(int) = Load[?] : &:r50_13, ~m44_24 +# 50| m50_15(int) = Store[?] : &:r50_11, r50_14 +# 50| m50_16(int[2]) = Chi : total:m50_9, partial:m50_15 +# 55| v55_1(void) = NoOp : +# 44| v44_25(void) = ReturnIndirection[b] : &:r44_7, m44_8 +# 44| v44_26(void) = ReturnIndirection[c] : &:r44_11, m48_7 +# 44| v44_27(void) = ReturnIndirection[d] : &:r44_15, m44_16 +# 44| v44_28(void) = ReturnIndirection[e] : &:r44_19, m44_20 +# 44| v44_29(void) = ReturnIndirection[f] : &:r44_23, m44_24 +# 44| v44_30(void) = ReturnVoid : +# 44| v44_31(void) = AliasedUse : m44_3 +# 44| v44_32(void) = ExitFunction : + +# 44| Block 1 +# 44| v44_33(void) = Unreached : +>>>>>>> ad6e7a0f0f8 (C++: Add `__try` with load test case) try_except.cpp: # 6| void f_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 e30106d35204..e988beb52ab6 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:63:13:63:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:56:6:56:6 | void k(int*, int*, int*, int*, int*) | void k(int*, int*, int*, int*, int*) | +| try_except.c:63:13:63:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:56:6:56:6 | void k(int*, int*, int*, int*, int*) | void k(int*, int*, int*, int*, 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 26b6d8a18170..39501758ec8a 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,99 @@ try_except.c: # 46| v46_9(void) = ReturnVoid : #-----| Goto -> Block 1 +# 56| void k(int*, int*, 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 +# 56| r56_16(glval) = VariableAddress[e] : +# 56| mu56_17(int *) = InitializeParameter[e] : &:r56_16 +# 56| r56_18(int *) = Load[e] : &:r56_16, ~m? +# 56| mu56_19(unknown) = InitializeIndirection[e] : &:r56_18 +# 56| r56_20(glval) = VariableAddress[f] : +# 56| mu56_21(int *) = InitializeParameter[f] : &:r56_20 +# 56| r56_22(int *) = Load[f] : &:r56_20, ~m? +# 56| mu56_23(unknown) = InitializeIndirection[f] : &:r56_22 +# 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? +# 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 +# 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? +# 61| mu61_5(int) = Store[y] : &:r61_1, r61_4 +#-----| Goto -> Block 7 + +# 56| Block 1 +# 56| v56_24(void) = AliasedUse : ~m? +# 56| v56_25(void) = ExitFunction : + +# 56| Block 2 +# 56| v56_26(void) = Unwind : +#-----| Goto -> Block 1 + +# 63| Block 3 +# 63| r63_1(int) = Constant[0] : +# 63| r63_2(bool) = CompareEQ : r63_7, r63_1 +# 63| v63_3(void) = ConditionalBranch : r63_2 +#-----| False -> Block 4 +#-----| True -> Block 2 + +# 63| Block 4 +# 63| r63_4(int) = Constant[1] : +# 63| r63_5(bool) = CompareEQ : r63_7, r63_4 +# 63| v63_6(void) = ConditionalBranch : r63_5 +#-----| True -> Block 6 + +# 63| Block 5 +# 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 3 +#-----| True -> Block 2 + +# 64| Block 6 +# 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 7 + +# 66| Block 7 +# 66| v66_1(void) = NoOp : +# 56| v56_27(void) = ReturnIndirection[b] : &:r56_6, ~m? +# 56| v56_28(void) = ReturnIndirection[c] : &:r56_10, ~m? +# 56| v56_29(void) = ReturnIndirection[d] : &:r56_14, ~m? +# 56| v56_30(void) = ReturnIndirection[e] : &:r56_18, ~m? +# 56| v56_31(void) = ReturnIndirection[f] : &:r56_22, ~m? +# 56| v56_32(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..8efb9b0ef1d1 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 *e, int *f) { + 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); } } From 3eb768c1e9579e2375e8511e2f3dda2794bd590c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 13 Jun 2025 22:54:57 +0200 Subject: [PATCH 2/4] C++: Generate SEH edges for pointer dereference stores in `__try` blocks --- .../raw/internal/TranslatedExpr.qll | 9 +- .../library-tests/ir/ir/aliased_ir.expected | 175 ++++++++++-------- .../ir/ir/raw_consistency.expected | 2 - .../test/library-tests/ir/ir/raw_ir.expected | 34 ++-- 4 files changed, 125 insertions(+), 95 deletions(-) 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..4e67a7cea381 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 @@ -1945,7 +1945,14 @@ 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 + expr.getLValue() instanceof PointerDereferenceExpr and + kind instanceof SehExceptionEdge and + exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) 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/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index ca4ba7385f88..bfddb2a179cd 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39194,7 +39194,6 @@ try_except.c: # 32| Block 7 # 32| v32_10(void) = Unreached : -<<<<<<< HEAD # 46| void j(int) # 46| Block 0 # 46| v46_1(void) = EnterFunction : @@ -39258,82 +39257,104 @@ try_except.c: # 46| Block 7 # 46| v46_10(void) = Unreached : -======= -# 44| void i(int*, int*, int*, int*, int*) -# 44| Block 0 -# 44| v44_1(void) = EnterFunction : -# 44| m44_2(unknown) = AliasedDefinition : -# 44| m44_3(unknown) = InitializeNonLocal : -# 44| m44_4(unknown) = Chi : total:m44_2, partial:m44_3 -# 44| r44_5(glval) = VariableAddress[b] : -# 44| m44_6(int *) = InitializeParameter[b] : &:r44_5 -# 44| r44_7(int *) = Load[b] : &:r44_5, m44_6 -# 44| m44_8(unknown) = InitializeIndirection[b] : &:r44_7 -# 44| r44_9(glval) = VariableAddress[c] : -# 44| m44_10(int *) = InitializeParameter[c] : &:r44_9 -# 44| r44_11(int *) = Load[c] : &:r44_9, m44_10 -# 44| m44_12(unknown) = InitializeIndirection[c] : &:r44_11 -# 44| r44_13(glval) = VariableAddress[d] : -# 44| m44_14(int *) = InitializeParameter[d] : &:r44_13 -# 44| r44_15(int *) = Load[d] : &:r44_13, m44_14 -# 44| m44_16(unknown) = InitializeIndirection[d] : &:r44_15 -# 44| r44_17(glval) = VariableAddress[e] : -# 44| m44_18(int *) = InitializeParameter[e] : &:r44_17 -# 44| r44_19(int *) = Load[e] : &:r44_17, m44_18 -# 44| m44_20(unknown) = InitializeIndirection[e] : &:r44_19 -# 44| r44_21(glval) = VariableAddress[f] : -# 44| m44_22(int *) = InitializeParameter[f] : &:r44_21 -# 44| r44_23(int *) = Load[f] : &:r44_21, m44_22 -# 44| m44_24(unknown) = InitializeIndirection[f] : &:r44_23 -# 45| r45_1(glval) = VariableAddress[x] : -# 45| r45_2(int) = Constant[0] : -# 45| m45_3(int) = Store[x] : &:r45_1, r45_2 -# 47| r47_1(glval) = VariableAddress[b] : -# 47| r47_2(int *) = Load[b] : &:r47_1, m44_6 -# 47| r47_3(int) = Load[?] : &:r47_2, ~m44_8 -# 47| r47_4(glval) = VariableAddress[x] : -# 47| m47_5(int) = Store[x] : &:r47_4, r47_3 -# 48| r48_1(glval) = VariableAddress[x] : -# 48| r48_2(int) = Load[x] : &:r48_1, m47_5 -# 48| r48_3(glval) = VariableAddress[c] : -# 48| r48_4(int *) = Load[c] : &:r48_3, m44_10 -# 48| r48_5(glval) = CopyValue : r48_4 -# 48| m48_6(int) = Store[?] : &:r48_5, r48_2 -# 48| m48_7(unknown) = Chi : total:m44_12, partial:m48_6 -# 49| r49_1(glval) = VariableAddress[y] : -# 49| r49_2(glval) = VariableAddress[d] : -# 49| r49_3(int *) = Load[d] : &:r49_2, m44_14 -# 49| r49_4(int) = Load[?] : &:r49_3, ~m44_16 -# 49| m49_5(int) = Store[y] : &:r49_1, r49_4 -# 50| r50_1(glval) = VariableAddress[x] : -# 50| m50_2(int[2]) = Uninitialized[x] : &:r50_1 -# 50| r50_3(int) = Constant[0] : -# 50| r50_4(glval) = PointerAdd[4] : r50_1, r50_3 -# 50| r50_5(glval) = VariableAddress[e] : -# 50| r50_6(int *) = Load[e] : &:r50_5, m44_18 -# 50| r50_7(int) = Load[?] : &:r50_6, ~m44_20 -# 50| m50_8(int) = Store[?] : &:r50_4, r50_7 -# 50| m50_9(int[2]) = Chi : total:m50_2, partial:m50_8 -# 50| r50_10(int) = Constant[1] : -# 50| r50_11(glval) = PointerAdd[4] : r50_1, r50_10 -# 50| r50_12(glval) = VariableAddress[f] : -# 50| r50_13(int *) = Load[f] : &:r50_12, m44_22 -# 50| r50_14(int) = Load[?] : &:r50_13, ~m44_24 -# 50| m50_15(int) = Store[?] : &:r50_11, r50_14 -# 50| m50_16(int[2]) = Chi : total:m50_9, partial:m50_15 -# 55| v55_1(void) = NoOp : -# 44| v44_25(void) = ReturnIndirection[b] : &:r44_7, m44_8 -# 44| v44_26(void) = ReturnIndirection[c] : &:r44_11, m48_7 -# 44| v44_27(void) = ReturnIndirection[d] : &:r44_15, m44_16 -# 44| v44_28(void) = ReturnIndirection[e] : &:r44_19, m44_20 -# 44| v44_29(void) = ReturnIndirection[f] : &:r44_23, m44_24 -# 44| v44_30(void) = ReturnVoid : -# 44| v44_31(void) = AliasedUse : m44_3 -# 44| v44_32(void) = ExitFunction : - -# 44| Block 1 -# 44| v44_33(void) = Unreached : ->>>>>>> ad6e7a0f0f8 (C++: Add `__try` with load test case) + +# 56| void k(int*, int*, 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 +# 56| r56_17(glval) = VariableAddress[e] : +# 56| m56_18(int *) = InitializeParameter[e] : &:r56_17 +# 56| r56_19(int *) = Load[e] : &:r56_17, m56_18 +# 56| m56_20(unknown) = InitializeIndirection[e] : &:r56_19 +# 56| r56_21(glval) = VariableAddress[f] : +# 56| m56_22(int *) = InitializeParameter[f] : &:r56_21 +# 56| r56_23(int *) = Load[f] : &:r56_21, m56_22 +# 56| m56_24(unknown) = InitializeIndirection[f] : &:r56_23 +# 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 +# 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 1 +#-----| SEH Exception -> Block 4 + +# 61| Block 1 +# 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 +# 61| m61_5(int) = Store[y] : &:r61_1, r61_4 +#-----| Goto -> Block 6 + +# 63| Block 2 +# 63| r63_1(int) = Constant[0] : +# 63| r63_2(bool) = CompareEQ : r63_7, r63_1 +# 63| v63_3(void) = ConditionalBranch : r63_2 +#-----| False -> Block 3 +#-----| True -> Block 7 + +# 63| Block 3 +# 63| r63_4(int) = Constant[1] : +# 63| r63_5(bool) = CompareEQ : r63_7, r63_4 +# 63| v63_6(void) = ConditionalBranch : r63_5 +#-----| False -> Block 7 +#-----| True -> Block 5 + +# 63| Block 4 +# 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 2 +#-----| True -> Block 7 + +# 64| Block 5 +# 64| r64_1(glval) = FunctionAddress[sink] : +# 64| r64_2(glval) = VariableAddress[x] : +# 64| r64_3(int) = Load[x] : &:r64_2, m59_5 +# 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 6 + +# 66| Block 6 +# 66| m66_1(unknown) = Phi : from 1:~m56_4, from 5:~m64_6 +# 66| v66_2(void) = NoOp : +# 56| v56_25(void) = ReturnIndirection[b] : &:r56_7, m56_8 +# 56| v56_26(void) = ReturnIndirection[c] : &:r56_11, m60_7 +# 56| v56_27(void) = ReturnIndirection[d] : &:r56_15, m56_16 +# 56| v56_28(void) = ReturnIndirection[e] : &:r56_19, m56_20 +# 56| v56_29(void) = ReturnIndirection[f] : &:r56_23, m56_24 +# 56| v56_30(void) = ReturnVoid : +# 56| v56_31(void) = AliasedUse : ~m66_1 +# 56| v56_32(void) = ExitFunction : + +# 56| Block 7 +# 56| v56_33(void) = Unreached : try_except.cpp: # 6| void f_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 e988beb52ab6..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:63:13:63:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:56:6:56:6 | void k(int*, int*, int*, int*, int*) | void k(int*, int*, int*, int*, int*) | -| try_except.c:63:13:63:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:56:6:56:6 | void k(int*, int*, int*, int*, int*) | void k(int*, int*, int*, int*, 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 39501758ec8a..7d4024c27e98 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37572,12 +37572,8 @@ try_except.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 -# 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? -# 61| mu61_5(int) = Store[y] : &:r61_1, r61_4 -#-----| Goto -> Block 7 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 56| Block 1 # 56| v56_24(void) = AliasedUse : ~m? @@ -37587,36 +37583,44 @@ try_except.c: # 56| v56_26(void) = Unwind : #-----| Goto -> Block 1 -# 63| Block 3 +# 61| Block 3 +# 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? +# 61| mu61_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_7, r63_1 # 63| v63_3(void) = ConditionalBranch : r63_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 63| Block 4 +# 63| Block 5 # 63| r63_4(int) = Constant[1] : # 63| r63_5(bool) = CompareEQ : r63_7, r63_4 # 63| v63_6(void) = ConditionalBranch : r63_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 63| Block 5 +# 63| Block 6 # 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 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 64| Block 6 +# 64| Block 7 # 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 7 +#-----| Goto -> Block 8 -# 66| Block 7 +# 66| Block 8 # 66| v66_1(void) = NoOp : # 56| v56_27(void) = ReturnIndirection[b] : &:r56_6, ~m? # 56| v56_28(void) = ReturnIndirection[c] : &:r56_10, ~m? From 9d6a1a98853c25e1dac05b9b2db4e58e32ca14ff Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Sat, 14 Jun 2025 00:00:37 +0200 Subject: [PATCH 3/4] C++: Generate SEH edges for pointer dereference loads in `__try` blocks --- .../raw/internal/TranslatedExpr.qll | 9 +- .../library-tests/ir/ir/aliased_ir.expected | 85 +++++++++++-------- .../test/library-tests/ir/ir/raw_ir.expected | 50 ++++++----- 3 files changed, 85 insertions(+), 59 deletions(-) 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 4e67a7cea381..279477d9588b 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 @@ -400,7 +400,14 @@ 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 + expr instanceof PointerDereferenceExpr and + kind instanceof SehExceptionEdge and + exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) 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/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index bfddb2a179cd..78d3798df7c5 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -39290,70 +39290,81 @@ try_except.c: # 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 -# 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 1 -#-----| SEH Exception -> Block 4 +#-----| 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 1 +# 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 -# 61| m61_5(int) = Store[y] : &:r61_1, r61_4 -#-----| Goto -> Block 6 +#-----| 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 2 +# 63| Block 4 # 63| r63_1(int) = Constant[0] : -# 63| r63_2(bool) = CompareEQ : r63_7, r63_1 +# 63| r63_2(bool) = CompareEQ : r63_9, r63_1 # 63| v63_3(void) = ConditionalBranch : r63_2 -#-----| False -> Block 3 -#-----| True -> Block 7 +#-----| False -> Block 5 +#-----| True -> Block 9 -# 63| Block 3 +# 63| Block 5 # 63| r63_4(int) = Constant[1] : -# 63| r63_5(bool) = CompareEQ : r63_7, r63_4 +# 63| r63_5(bool) = CompareEQ : r63_9, r63_4 # 63| v63_6(void) = ConditionalBranch : r63_5 -#-----| False -> Block 7 -#-----| True -> Block 5 - -# 63| Block 4 -# 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 2 +#-----| False -> Block 9 #-----| True -> Block 7 -# 64| Block 5 +# 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, m59_5 +# 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 6 +#-----| Goto -> Block 8 -# 66| Block 6 -# 66| m66_1(unknown) = Phi : from 1:~m56_4, from 5:~m64_6 -# 66| v66_2(void) = NoOp : +# 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_25(void) = ReturnIndirection[b] : &:r56_7, m56_8 -# 56| v56_26(void) = ReturnIndirection[c] : &:r56_11, m60_7 +# 56| v56_26(void) = ReturnIndirection[c] : &:r56_11, m66_1 # 56| v56_27(void) = ReturnIndirection[d] : &:r56_15, m56_16 # 56| v56_28(void) = ReturnIndirection[e] : &:r56_19, m56_20 # 56| v56_29(void) = ReturnIndirection[f] : &:r56_23, m56_24 # 56| v56_30(void) = ReturnVoid : -# 56| v56_31(void) = AliasedUse : ~m66_1 +# 56| v56_31(void) = AliasedUse : ~m66_2 # 56| v56_32(void) = ExitFunction : -# 56| Block 7 +# 56| Block 9 # 56| v56_33(void) = Unreached : try_except.cpp: 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 7d4024c27e98..b521dd6b503c 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -37564,16 +37564,8 @@ try_except.c: # 59| r59_1(glval) = VariableAddress[b] : # 59| r59_2(int *) = Load[b] : &:r59_1, ~m? # 59| r59_3(int) = Load[?] : &:r59_2, ~m? -# 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 3 -#-----| SEH Exception -> Block 6 +#-----| SEH Exception -> Block 8 # 56| Block 1 # 56| v56_24(void) = AliasedUse : ~m? @@ -37583,44 +37575,60 @@ try_except.c: # 56| v56_26(void) = Unwind : #-----| Goto -> Block 1 -# 61| Block 3 +# 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? -# 61| mu61_5(int) = Store[y] : &:r61_1, r61_4 -#-----| Goto -> Block 8 +#-----| 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 4 +# 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 5 +#-----| False -> Block 7 #-----| True -> Block 2 -# 63| Block 5 +# 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 7 +#-----| True -> Block 9 -# 63| Block 6 +# 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 4 +#-----| False -> Block 6 #-----| True -> Block 2 -# 64| Block 7 +# 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 8 +#-----| Goto -> Block 10 -# 66| Block 8 +# 66| Block 10 # 66| v66_1(void) = NoOp : # 56| v56_27(void) = ReturnIndirection[b] : &:r56_6, ~m? # 56| v56_28(void) = ReturnIndirection[c] : &:r56_10, ~m? From 4228828b66252843647489a2bc91624fb5f6b436 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 16 Jun 2025 15:02:08 +0200 Subject: [PATCH 4/4] C++: Address review comments --- .../raw/internal/TranslatedExpr.qll | 14 +++++++--- .../library-tests/ir/ir/PrintAST.expected | 6 +---- .../library-tests/ir/ir/aliased_ir.expected | 26 ++++++------------- .../test/library-tests/ir/ir/raw_ir.expected | 26 ++++++------------- cpp/ql/test/library-tests/ir/ir/try_except.c | 2 +- 5 files changed, 28 insertions(+), 46 deletions(-) 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 279477d9588b..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. @@ -403,9 +411,8 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad ( result = this.getParent().getChildSuccessor(this, kind) or - expr instanceof PointerDereferenceExpr and + hasSehExceptionEdge(expr) and kind instanceof SehExceptionEdge and - exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e)) ) } @@ -1955,9 +1962,8 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr { ( result = this.getParent().getChildSuccessor(this, kind) or - expr.getLValue() instanceof PointerDereferenceExpr and + hasSehExceptionEdge(expr.getLValue()) and kind instanceof SehExceptionEdge and - exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) and result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge e)) ) } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 998dc4862892..d3ef1de1e13a 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -49689,7 +49689,7 @@ try_except.c: # 52| Type = [IntType] int # 52| ValueCategory = prvalue(load) # 54| getStmt(2): [ReturnStmt] return ... -# 56| [TopLevelFunction] void k(int*, int*, int*, int*, int*) +# 56| [TopLevelFunction] void k(int*, int*, int*) # 56| : # 56| getParameter(0): [Parameter] b # 56| Type = [IntPointerType] int * @@ -49697,10 +49697,6 @@ try_except.c: # 56| Type = [IntPointerType] int * # 56| getParameter(2): [Parameter] d # 56| Type = [IntPointerType] int * -# 56| getParameter(3): [Parameter] e -# 56| Type = [IntPointerType] int * -# 56| getParameter(4): [Parameter] f -# 56| Type = [IntPointerType] int * # 56| getEntryPoint(): [BlockStmt] { ... } # 57| getStmt(0): [DeclStmt] declaration # 57| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x 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 78d3798df7c5..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,7 +39258,7 @@ try_except.c: # 46| Block 7 # 46| v46_10(void) = Unreached : -# 56| void k(int*, int*, int*, int*, int*) +# 56| void k(int*, int*, int*) # 56| Block 0 # 56| v56_1(void) = EnterFunction : # 56| m56_2(unknown) = AliasedDefinition : @@ -39276,14 +39276,6 @@ try_except.c: # 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 -# 56| r56_17(glval) = VariableAddress[e] : -# 56| m56_18(int *) = InitializeParameter[e] : &:r56_17 -# 56| r56_19(int *) = Load[e] : &:r56_17, m56_18 -# 56| m56_20(unknown) = InitializeIndirection[e] : &:r56_19 -# 56| r56_21(glval) = VariableAddress[f] : -# 56| m56_22(int *) = InitializeParameter[f] : &:r56_21 -# 56| r56_23(int *) = Load[f] : &:r56_21, m56_22 -# 56| m56_24(unknown) = InitializeIndirection[f] : &:r56_23 # 57| r57_1(glval) = VariableAddress[x] : # 57| r57_2(int) = Constant[0] : # 57| m57_3(int) = Store[x] : &:r57_1, r57_2 @@ -39355,17 +39347,15 @@ try_except.c: # 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_25(void) = ReturnIndirection[b] : &:r56_7, m56_8 -# 56| v56_26(void) = ReturnIndirection[c] : &:r56_11, m66_1 -# 56| v56_27(void) = ReturnIndirection[d] : &:r56_15, m56_16 -# 56| v56_28(void) = ReturnIndirection[e] : &:r56_19, m56_20 -# 56| v56_29(void) = ReturnIndirection[f] : &:r56_23, m56_24 -# 56| v56_30(void) = ReturnVoid : -# 56| v56_31(void) = AliasedUse : ~m66_2 -# 56| v56_32(void) = ExitFunction : +# 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_33(void) = Unreached : +# 56| v56_23(void) = Unreached : try_except.cpp: # 6| void f_cpp() 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 b521dd6b503c..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,7 +37533,7 @@ try_except.c: # 46| v46_9(void) = ReturnVoid : #-----| Goto -> Block 1 -# 56| void k(int*, int*, int*, int*, int*) +# 56| void k(int*, int*, int*) # 56| Block 0 # 56| v56_1(void) = EnterFunction : # 56| mu56_2(unknown) = AliasedDefinition : @@ -37550,14 +37550,6 @@ try_except.c: # 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 -# 56| r56_16(glval) = VariableAddress[e] : -# 56| mu56_17(int *) = InitializeParameter[e] : &:r56_16 -# 56| r56_18(int *) = Load[e] : &:r56_16, ~m? -# 56| mu56_19(unknown) = InitializeIndirection[e] : &:r56_18 -# 56| r56_20(glval) = VariableAddress[f] : -# 56| mu56_21(int *) = InitializeParameter[f] : &:r56_20 -# 56| r56_22(int *) = Load[f] : &:r56_20, ~m? -# 56| mu56_23(unknown) = InitializeIndirection[f] : &:r56_22 # 57| r57_1(glval) = VariableAddress[x] : # 57| r57_2(int) = Constant[0] : # 57| mu57_3(int) = Store[x] : &:r57_1, r57_2 @@ -37568,11 +37560,11 @@ try_except.c: #-----| SEH Exception -> Block 8 # 56| Block 1 -# 56| v56_24(void) = AliasedUse : ~m? -# 56| v56_25(void) = ExitFunction : +# 56| v56_16(void) = AliasedUse : ~m? +# 56| v56_17(void) = ExitFunction : # 56| Block 2 -# 56| v56_26(void) = Unwind : +# 56| v56_18(void) = Unwind : #-----| Goto -> Block 1 # 59| Block 3 @@ -37630,12 +37622,10 @@ try_except.c: # 66| Block 10 # 66| v66_1(void) = NoOp : -# 56| v56_27(void) = ReturnIndirection[b] : &:r56_6, ~m? -# 56| v56_28(void) = ReturnIndirection[c] : &:r56_10, ~m? -# 56| v56_29(void) = ReturnIndirection[d] : &:r56_14, ~m? -# 56| v56_30(void) = ReturnIndirection[e] : &:r56_18, ~m? -# 56| v56_31(void) = ReturnIndirection[f] : &:r56_22, ~m? -# 56| v56_32(void) = ReturnVoid : +# 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: 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 8efb9b0ef1d1..27eb8d24e174 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.c +++ b/cpp/ql/test/library-tests/ir/ir/try_except.c @@ -53,7 +53,7 @@ void j(int b) { } } -void k(int *b, int *c, int *d, int *e, int *f) { +void k(int *b, int *c, int *d) { int x = 0; __try { x = *b;