Skip to content

Commit d2964a7

Browse files
committed
C++: Also handle '__finally' blocks.
1 parent 3c8efa8 commit d2964a7

File tree

5 files changed

+38
-14
lines changed

5 files changed

+38
-14
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ private class TryOrMicrosoftTryStmt extends Stmt {
263263
or
264264
this instanceof MicrosoftTryExceptStmt and
265265
result = 1
266+
or
267+
this instanceof MicrosoftTryFinallyStmt and
268+
result = 0
266269
}
267270

268271
/** Gets the `body` statement of this statement. */
@@ -279,6 +282,9 @@ private class TryOrMicrosoftTryStmt extends Stmt {
279282
i = 0 and
280283
result = this.(MicrosoftTryExceptStmt).getExcept()
281284
}
285+
286+
/** Gets the `finally` statement (usually a BlockStmt), if any. */
287+
Stmt getFinally() { result = this.(MicrosoftTryFinallyStmt).getFinally() }
282288
}
283289

284290
/**
@@ -291,6 +297,9 @@ class TranslatedTryStmt extends TranslatedStmt {
291297
id = 0 and result = getBody()
292298
or
293299
result = getHandler(id - 1)
300+
or
301+
id = stmt.getNumberOfCatchClauses() + 1 and
302+
result = this.getFinally()
294303
}
295304

296305
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -302,8 +311,20 @@ class TranslatedTryStmt extends TranslatedStmt {
302311
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
303312

304313
override Instruction getChildSuccessor(TranslatedElement child) {
305-
// All children go to the successor of the `try`.
306-
child = getAChild() and result = getParent().getChildSuccessor(this)
314+
// All non-finally children go to the successor of the `try` if
315+
// there is no finally block, but if there is a finally block
316+
// then we go to that one.
317+
child = [getBody(), getHandler(_)] and
318+
(
319+
not exists(this.getFinally()) and
320+
result = getParent().getChildSuccessor(this)
321+
or
322+
result = this.getFinally().getFirstInstruction()
323+
)
324+
or
325+
// And after the finally block we go to the successor of the `try`.
326+
child = this.getFinally() and
327+
result = getParent().getChildSuccessor(this)
307328
}
308329

309330
final Instruction getNextHandler(TranslatedHandler handler) {
@@ -327,6 +348,8 @@ class TranslatedTryStmt extends TranslatedStmt {
327348
result = getTranslatedStmt(stmt.getHandlerStmt(index))
328349
}
329350

351+
private TranslatedStmt getFinally() { result = getTranslatedStmt(stmt.getFinally()) }
352+
330353
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
331354
}
332355

cpp/ql/test/library-tests/ir/ir/operand_locations.expected

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9162,7 +9162,7 @@
91629162
| try_except.c:11:19:11:19 | Arg(0) | 0:r11_2 |
91639163
| try_except.c:18:6:18:6 | ChiPartial | partial:m18_3 |
91649164
| try_except.c:18:6:18:6 | ChiTotal | total:m18_2 |
9165-
| try_except.c:18:6:18:6 | SideEffect | ~m23_5 |
9165+
| try_except.c:18:6:18:6 | SideEffect | ~m26_6 |
91669166
| try_except.c:19:7:19:7 | Address | &:r19_1 |
91679167
| try_except.c:19:10:19:10 | Address | &:r19_3 |
91689168
| try_except.c:19:13:19:14 | StoreValue | r19_4 |
@@ -9180,3 +9180,10 @@
91809180
| try_except.c:23:5:23:17 | ChiTotal | total:m21_5 |
91819181
| try_except.c:23:5:23:17 | SideEffect | ~m21_5 |
91829182
| try_except.c:23:19:23:19 | Arg(0) | 0:r23_2 |
9183+
| try_except.c:26:5:26:8 | CallTarget | func:r26_1 |
9184+
| try_except.c:26:5:26:8 | ChiPartial | partial:m26_5 |
9185+
| try_except.c:26:5:26:8 | ChiTotal | total:m23_5 |
9186+
| try_except.c:26:5:26:8 | SideEffect | ~m23_5 |
9187+
| try_except.c:26:10:26:10 | Address | &:r26_2 |
9188+
| try_except.c:26:10:26:10 | Arg(0) | 0:r26_3 |
9189+
| try_except.c:26:10:26:10 | Load | m22_4 |

cpp/ql/test/library-tests/ir/ir/raw_consistency.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ sideEffectWithoutPrimary
88
instructionWithoutSuccessor
99
| 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() |
1010
| 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() |
11-
| 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() |
1211
ambiguousSuccessors
1312
unexplainedLoop
1413
unnecessaryPhiInstruction

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10471,14 +10471,12 @@ try_except.c:
1047110471
# 23| r23_2(int) = Constant[0] :
1047210472
# 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2
1047310473
# 23| mu23_4(unknown) = ^CallSideEffect : ~m?
10474+
# 26| r26_1(glval<unknown>) = FunctionAddress[sink] :
10475+
# 26| r26_2(glval<int>) = VariableAddress[x] :
10476+
# 26| r26_3(int) = Load[x] : &:r26_2, ~m?
10477+
# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3
10478+
# 26| mu26_5(unknown) = ^CallSideEffect : ~m?
1047410479
# 28| v28_1(void) = NoOp :
1047510480
# 18| v18_4(void) = ReturnVoid :
1047610481
# 18| v18_5(void) = AliasedUse : ~m?
1047710482
# 18| v18_6(void) = ExitFunction :
10478-
10479-
# 26| Block 1
10480-
# 26| r26_1(glval<unknown>) = FunctionAddress[sink] :
10481-
# 26| r26_2(glval<int>) = VariableAddress[x] :
10482-
# 26| r26_3(int) = Load[x] : &:r26_2, ~m?
10483-
# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3
10484-
# 26| mu26_5(unknown) = ^CallSideEffect : ~m?

cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,13 @@ instructionWithoutSuccessor
3333
| misc.c:174:55:174:60 | Store: (char ****)... | Instruction 'Store: (char ****)...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() |
3434
| ms_try_except.cpp:9:19:9:19 | Load: j | Instruction 'Load: j' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
3535
| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
36-
| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
3736
| ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | Instruction 'Sub: ... - ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
3837
| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) |
3938
| ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) |
4039
| ms_try_mix.cpp:20:15:20:39 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) |
4140
| ms_try_mix.cpp:21:16:21:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) |
4241
| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
43-
| ms_try_mix.cpp:38:16:38:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
4442
| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
45-
| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } | Instruction 'NoOp: { ... }' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
4643
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) |
4744
| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) |
4845
| stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() |

0 commit comments

Comments
 (0)