diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 4153f37c024..2b9d5831518 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -14822,3 +14822,112 @@ struct_init.cpp: # 41| Type = [PointerType] Info * # 41| ValueCategory = prvalue # 42| getStmt(2): [ReturnStmt] return ... +try_except.c: +# 3| [TopLevelFunction] void ProbeFunction() +# 3| : +# 4| [TopLevelFunction] void sink() +# 4| : +# 6| [TopLevelFunction] void f() +# 6| : +# 6| getEntryPoint(): [BlockStmt] { ... } +# 7| getStmt(0): [DeclStmt] declaration +# 7| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 7| Type = [IntType] int +# 7| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 7| Type = [IntType] int +# 7| getVariable().getInitializer(): [Initializer] initializer for y +# 7| getExpr(): [Literal] 0 +# 7| Type = [IntType] int +# 7| Value = [Literal] 0 +# 7| ValueCategory = prvalue +# 8| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 8| getStmt(): [BlockStmt] { ... } +# 9| getStmt(0): [ExprStmt] ExprStmt +# 9| getExpr(): [FunctionCall] call to ProbeFunction +# 9| Type = [VoidType] void +# 9| ValueCategory = prvalue +# 9| getArgument(0): [Literal] 0 +# 9| Type = [IntType] int +# 9| Value = [Literal] 0 +# 9| ValueCategory = prvalue +# 10| getStmt(1): [ExprStmt] ExprStmt +# 10| getExpr(): [AssignExpr] ... = ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| getLValue(): [VariableAccess] x +# 10| Type = [IntType] int +# 10| ValueCategory = lvalue +# 10| getRValue(): [VariableAccess] y +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) +# 11| getStmt(2): [ExprStmt] ExprStmt +# 11| getExpr(): [FunctionCall] call to ProbeFunction +# 11| Type = [VoidType] void +# 11| ValueCategory = prvalue +# 11| getArgument(0): [Literal] 0 +# 11| Type = [IntType] int +# 11| Value = [Literal] 0 +# 11| ValueCategory = prvalue +# 13| getCondition(): [Literal] 0 +# 13| Type = [IntType] int +# 13| Value = [Literal] 0 +# 13| ValueCategory = prvalue +# 13| getExcept(): [BlockStmt] { ... } +# 14| getStmt(0): [ExprStmt] ExprStmt +# 14| getExpr(): [FunctionCall] call to sink +# 14| Type = [VoidType] void +# 14| ValueCategory = prvalue +# 14| getArgument(0): [VariableAccess] x +# 14| Type = [IntType] int +# 14| ValueCategory = prvalue(load) +# 16| getStmt(2): [ReturnStmt] return ... +# 18| [TopLevelFunction] void g() +# 18| : +# 18| getEntryPoint(): [BlockStmt] { ... } +# 19| getStmt(0): [DeclStmt] declaration +# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 19| Type = [IntType] int +# 19| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 19| Type = [IntType] int +# 19| getVariable().getInitializer(): [Initializer] initializer for y +# 19| getExpr(): [Literal] 0 +# 19| Type = [IntType] int +# 19| Value = [Literal] 0 +# 19| ValueCategory = prvalue +# 20| getStmt(1): [MicrosoftTryFinallyStmt] __try { ... } __finally { ... } +# 20| getStmt(): [BlockStmt] { ... } +# 21| getStmt(0): [ExprStmt] ExprStmt +# 21| getExpr(): [FunctionCall] call to ProbeFunction +# 21| Type = [VoidType] void +# 21| ValueCategory = prvalue +# 21| getArgument(0): [Literal] 0 +# 21| Type = [IntType] int +# 21| Value = [Literal] 0 +# 21| ValueCategory = prvalue +# 22| getStmt(1): [ExprStmt] ExprStmt +# 22| getExpr(): [AssignExpr] ... = ... +# 22| Type = [IntType] int +# 22| ValueCategory = prvalue +# 22| getLValue(): [VariableAccess] x +# 22| Type = [IntType] int +# 22| ValueCategory = lvalue +# 22| getRValue(): [VariableAccess] y +# 22| Type = [IntType] int +# 22| ValueCategory = prvalue(load) +# 23| getStmt(2): [ExprStmt] ExprStmt +# 23| getExpr(): [FunctionCall] call to ProbeFunction +# 23| Type = [VoidType] void +# 23| ValueCategory = prvalue +# 23| getArgument(0): [Literal] 0 +# 23| Type = [IntType] int +# 23| Value = [Literal] 0 +# 23| ValueCategory = prvalue +# 25| getFinally(): [BlockStmt] { ... } +# 26| getStmt(0): [ExprStmt] ExprStmt +# 26| getExpr(): [FunctionCall] call to sink +# 26| Type = [VoidType] void +# 26| ValueCategory = prvalue +# 26| getArgument(0): [VariableAccess] x +# 26| Type = [IntType] int +# 26| ValueCategory = prvalue(load) +# 28| getStmt(2): [ReturnStmt] return ... diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected index 79887fffc1f..25cf1848a18 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected @@ -6,6 +6,8 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| try_except.c:7:13:7:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:19:13:19:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected index 79887fffc1f..25cf1848a18 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected @@ -6,6 +6,8 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| try_except.c:7:13:7:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:19:13:19:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index eb63841daba..023125105c9 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -9140,3 +9140,13 @@ | struct_init.cpp:41:21:41:32 | ChiTotal | total:m41_7 | | struct_init.cpp:41:21:41:32 | SideEffect | ~m41_7 | | struct_init.cpp:41:21:41:32 | Unary | r41_3 | +| try_except.c:6:6:6:6 | ChiPartial | partial:m6_3 | +| try_except.c:6:6:6:6 | ChiTotal | total:m6_2 | +| try_except.c:7:7:7:7 | Address | &:r7_1 | +| try_except.c:7:10:7:10 | Address | &:r7_3 | +| try_except.c:7:13:7:14 | StoreValue | r7_4 | +| try_except.c:18:6:18:6 | ChiPartial | partial:m18_3 | +| try_except.c:18:6:18:6 | ChiTotal | total:m18_2 | +| try_except.c:19:7:19:7 | Address | &:r19_1 | +| try_except.c:19:10:19:10 | Address | &:r19_3 | +| try_except.c:19:13:19:14 | StoreValue | r19_4 | 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 600d74bc916..87134ab2a15 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -6,6 +6,13 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| try_except.c:7:13:7:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:11:5:11:17 | CallSideEffect: call to ProbeFunction | Instruction 'CallSideEffect: call to ProbeFunction' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:13:13:13:13 | Constant: 0 | Instruction 'Constant: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:14:5:14:8 | CallSideEffect: call to sink | Instruction 'CallSideEffect: call to sink' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:19:13:19:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | +| try_except.c:23:5:23:17 | CallSideEffect: call to ProbeFunction | Instruction 'CallSideEffect: call to ProbeFunction' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | +| try_except.c:26:5:26:8 | CallSideEffect: call to sink | Instruction 'CallSideEffect: call to sink' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction 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 cb8bd0465da..b2a5d81d315 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -10410,3 +10410,83 @@ struct_init.cpp: # 36| v36_9(void) = ReturnVoid : # 36| v36_10(void) = AliasedUse : ~m? # 36| v36_11(void) = ExitFunction : + +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 + +# 13| Block 1 +# 13| r13_1(int) = Constant[0] : + +# 9| Block 2 +# 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? + +# 14| Block 2 +# 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? + +# 16| Block 4 +# 16| v16_1(void) = NoOp : +# 6| v6_4(void) = ReturnVoid : +# 6| v6_5(void) = AliasedUse : ~m? +# 6| v6_6(void) = ExitFunction : + +# 18| void g() +# 18| Block 0 +# 18| v18_1(void) = EnterFunction : +# 18| mu18_2(unknown) = AliasedDefinition : +# 18| mu18_3(unknown) = InitializeNonLocal : +# 19| r19_1(glval) = VariableAddress[x] : +# 19| mu19_2(int) = Uninitialized[x] : &:r19_1 +# 19| r19_3(glval) = VariableAddress[y] : +# 19| r19_4(int) = Constant[0] : +# 19| mu19_5(int) = Store[y] : &:r19_3, r19_4 + +# 21| Block 1 +# 21| r21_1(glval) = FunctionAddress[ProbeFunction] : +# 21| r21_2(int) = Constant[0] : +# 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 +# 21| mu21_4(unknown) = ^CallSideEffect : ~m? +# 22| r22_1(glval) = VariableAddress[y] : +# 22| r22_2(int) = Load[y] : &:r22_1, ~m? +# 22| r22_3(glval) = VariableAddress[x] : +# 22| mu22_4(int) = Store[x] : &:r22_3, r22_2 +# 23| r23_1(glval) = FunctionAddress[ProbeFunction] : +# 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| Block 1 +# 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| Block 3 +# 28| v28_1(void) = NoOp : +# 18| v18_4(void) = ReturnVoid : +# 18| v18_5(void) = AliasedUse : ~m? +# 18| v18_6(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.c b/cpp/ql/test/library-tests/ir/ir/try_except.c new file mode 100644 index 00000000000..a7018726428 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/try_except.c @@ -0,0 +1,28 @@ +// semmle-extractor-options: --microsoft + +void ProbeFunction(); +void sink(); + +void f() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __except (0) { + sink(x); + } +} + +void g() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __finally { + sink(x); + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected index 79887fffc1f..25cf1848a18 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected @@ -6,6 +6,8 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| try_except.c:7:13:7:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:19:13:19:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected index 79887fffc1f..25cf1848a18 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected @@ -6,6 +6,8 @@ missingOperandType duplicateChiOperand sideEffectWithoutPrimary instructionWithoutSuccessor +| try_except.c:7:13:7:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | +| try_except.c:19:13:19:14 | Store: 0 | Instruction 'Store: 0' has no successors in function '$@'. | try_except.c:18:6:18:6 | void g() | void g() | ambiguousSuccessors unexplainedLoop unnecessaryPhiInstruction