Skip to content

Commit 087a848

Browse files
authored
Merge pull request github#17430 from jketema/fix-finally-inconsistency
C++: Fix `__finally` related inconsistencies
2 parents e129914 + ca10953 commit 087a848

12 files changed

+93
-19
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,10 @@ newtype TTranslatedElement =
767767
} or
768768
// A statement
769769
TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or
770+
// The `__except` block of a `__try __except` statement
770771
TTranslatedMicrosoftTryExceptHandler(MicrosoftTryExceptStmt stmt) or
772+
// The `__finally` block of a `__try __finally` statement
773+
TTranslatedMicrosoftTryFinallyHandler(MicrosoftTryFinallyStmt stmt) or
771774
// A function
772775
TTranslatedFunction(Function func) { translateFunction(func) } or
773776
// A constructor init list

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

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,62 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
233233
}
234234
}
235235

236+
TranslatedMicrosoftTryFinallyHandler getTranslatedMicrosoftTryFinallyHandler(
237+
MicrosoftTryFinallyStmt tryFinally
238+
) {
239+
result.getAst() = tryFinally.getFinally()
240+
}
241+
242+
class TranslatedMicrosoftTryFinallyHandler extends TranslatedElement,
243+
TTranslatedMicrosoftTryFinallyHandler
244+
{
245+
MicrosoftTryFinallyStmt tryFinally;
246+
247+
TranslatedMicrosoftTryFinallyHandler() {
248+
this = TTranslatedMicrosoftTryFinallyHandler(tryFinally)
249+
}
250+
251+
final override string toString() { result = tryFinally.toString() }
252+
253+
final override Locatable getAst() { result = tryFinally.getFinally() }
254+
255+
override Instruction getFirstInstruction(EdgeKind kind) {
256+
result = this.getTranslatedFinally().getFirstInstruction(kind)
257+
}
258+
259+
override Instruction getALastInstructionInternal() {
260+
result = this.getTranslatedFinally().getALastInstruction()
261+
}
262+
263+
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
264+
child = this.getTranslatedFinally() and
265+
result = this.getParent().getChildSuccessor(this, kind)
266+
}
267+
268+
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
269+
270+
override TranslatedElement getChild(int id) {
271+
id = 0 and
272+
result = this.getTranslatedFinally()
273+
}
274+
275+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
276+
none()
277+
}
278+
279+
final override Function getFunction() { result = tryFinally.getEnclosingFunction() }
280+
281+
private TranslatedStmt getTranslatedFinally() {
282+
result = getTranslatedStmt(tryFinally.getFinally())
283+
}
284+
285+
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
286+
// A throw from within a `__finally` block flows to the handler for the parent of
287+
// the `__try`.
288+
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
289+
}
290+
}
291+
236292
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
237293
Stmt stmt;
238294

@@ -611,7 +667,9 @@ class TryOrMicrosoftTryStmt extends Stmt {
611667
}
612668

613669
/** Gets the `finally` statement (usually a BlockStmt), if any. */
614-
Stmt getFinally() { result = this.(MicrosoftTryFinallyStmt).getFinally() }
670+
TranslatedElement getTranslatedFinally() {
671+
result = getTranslatedMicrosoftTryFinallyHandler(this)
672+
}
615673
}
616674

617675
/**
@@ -681,11 +739,14 @@ class TranslatedTryStmt extends TranslatedStmt {
681739

682740
final override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
683741
result = this.getHandler(0).getFirstInstruction(kind)
742+
or
743+
not exists(this.getHandler(_)) and
744+
result = this.getFinally().getFirstInstruction(kind)
684745
}
685746

686747
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
687748

688-
private TranslatedStmt getFinally() { result = getTranslatedStmt(stmt.getFinally()) }
749+
private TranslatedElement getFinally() { result = stmt.getTranslatedFinally() }
689750

690751
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
691752
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3241,6 +3241,16 @@ ir.c:
32413241
# 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2
32423242
# 62| m62_4(unknown) = ^CallSideEffect : ~m57_4
32433243
# 62| m62_5(unknown) = Chi : total:m57_4, partial:m62_4
3244+
#-----| Exception -> Block 1
3245+
3246+
# 66| Block 1
3247+
# 66| r66_1(int) = Constant[1] :
3248+
# 66| r66_2(glval<int>) = VariableAddress[x] :
3249+
# 66| m66_3(int) = Store[x] : &:r66_2, r66_1
3250+
# 68| v68_1(void) = NoOp :
3251+
# 57| v57_5(void) = ReturnVoid :
3252+
# 57| v57_6(void) = AliasedUse : ~m62_5
3253+
# 57| v57_7(void) = ExitFunction :
32443254

32453255
# 70| void throw_in_try_with_throw_in_finally()
32463256
# 70| Block 0
@@ -3253,6 +3263,20 @@ ir.c:
32533263
# 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2
32543264
# 73| m73_4(unknown) = ^CallSideEffect : ~m70_4
32553265
# 73| m73_5(unknown) = Chi : total:m70_4, partial:m73_4
3266+
#-----| Exception -> Block 2
3267+
3268+
# 70| Block 1
3269+
# 70| v70_5(void) = Unwind :
3270+
# 70| v70_6(void) = AliasedUse : ~m76_5
3271+
# 70| v70_7(void) = ExitFunction :
3272+
3273+
# 76| Block 2
3274+
# 76| r76_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
3275+
# 76| r76_2(int) = Constant[0] :
3276+
# 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2
3277+
# 76| m76_4(unknown) = ^CallSideEffect : ~m73_5
3278+
# 76| m76_5(unknown) = Chi : total:m73_5, partial:m76_4
3279+
#-----| Exception -> Block 1
32563280

32573281
# 80| void raise_access_violation()
32583282
# 80| Block 0

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.c:62:5:62:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
10-
| ir.c:73:5:73:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.c:62:5:62:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
10-
| ir.c:73:5:73:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.c:62:5:62:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
10-
| ir.c:73:5:73:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
11-
| ir.c:76:5:76:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
129
ambiguousSuccessors
1310
unexplainedLoop
1411
unnecessaryPhiInstruction

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3022,6 +3022,7 @@ ir.c:
30223022
# 62| r62_2(int) = Constant[0] :
30233023
# 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2
30243024
# 62| mu62_4(unknown) = ^CallSideEffect : ~m?
3025+
#-----| Exception -> Block 3
30253026

30263027
# 57| Block 1
30273028
# 57| v57_4(void) = AliasedUse : ~m?
@@ -3048,6 +3049,7 @@ ir.c:
30483049
# 73| r73_2(int) = Constant[0] :
30493050
# 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2
30503051
# 73| mu73_4(unknown) = ^CallSideEffect : ~m?
3052+
#-----| Exception -> Block 3
30513053

30523054
# 70| Block 1
30533055
# 70| v70_4(void) = AliasedUse : ~m?
@@ -3062,6 +3064,7 @@ ir.c:
30623064
# 76| r76_2(int) = Constant[0] :
30633065
# 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2
30643066
# 76| mu76_4(unknown) = ^CallSideEffect : ~m?
3067+
#-----| Exception -> Block 2
30653068

30663069
# 78| Block 4
30673070
# 78| v78_1(void) = NoOp :

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.c:62:5:62:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
10-
| ir.c:73:5:73:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ missingOperandType
66
duplicateChiOperand
77
sideEffectWithoutPrimary
88
instructionWithoutSuccessor
9-
| ir.c:62:5:62:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:57:6:57:30 | void throw_in_try_with_finally() | void throw_in_try_with_finally() |
10-
| ir.c:73:5:73:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:70:6:70:39 | void throw_in_try_with_throw_in_finally() | void throw_in_try_with_throw_in_finally() |
119
ambiguousSuccessors
1210
unexplainedLoop
1311
unnecessaryPhiInstruction

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ missingOperandType
77
duplicateChiOperand
88
sideEffectWithoutPrimary
99
instructionWithoutSuccessor
10-
| ms_try_mix.cpp:38:5:38:5 | Chi: c106 | Instruction 'Chi: c106' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) |
11-
| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() |
1210
| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) |
1311
ambiguousSuccessors
1412
unexplainedLoop

0 commit comments

Comments
 (0)