Skip to content

Commit 4c8aec0

Browse files
authored
Merge pull request github#17421 from jketema/fix-except-inconsistency
C++: Fix IR inconsistency due to throwing `__except` block
2 parents ba5218d + 5f4fee0 commit 4c8aec0

File tree

10 files changed

+311
-333
lines changed

10 files changed

+311
-333
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
209209
(
210210
// Only generate the `Unwind` instruction if there is any exception
211211
// handling present in the function.
212-
exists(TryStmt try | try.getEnclosingFunction() = func) or
212+
exists(TryOrMicrosoftTryStmt try | try.getEnclosingFunction() = func)
213+
or
213214
exists(ThrowExpr throw | throw.getEnclosingFunction() = func)
215+
or
216+
exists(FunctionCall call | call.getEnclosingFunction() = func |
217+
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException()
218+
)
214219
)
215220
or
216221
tag = AliasedUseTag() and

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
7979
tag = TryExceptCompareOneBranch() and
8080
opcode instanceof Opcode::ConditionalBranch and
8181
resultType = getVoidType()
82-
or
83-
// unwind stack
84-
tag = UnwindTag() and
85-
opcode instanceof Opcode::Unwind and
86-
resultType = getVoidType()
8782
}
8883

8984
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
@@ -156,7 +151,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
156151
// TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that
157152
// we should continue execution at the point where the exception occurred. But we don't have
158153
// any instruction to model this behavior.
159-
result = this.getInstruction(UnwindTag())
154+
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
160155
or
161156
kind instanceof FalseEdge and
162157
result = this.getInstruction(TryExceptGenerateZero())
@@ -176,7 +171,7 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
176171
tag = TryExceptCompareZeroBranch() and
177172
(
178173
kind instanceof TrueEdge and
179-
result = this.getInstruction(UnwindTag())
174+
result = this.getExceptionSuccessorInstruction(any(GotoEdge edge))
180175
or
181176
kind instanceof FalseEdge and
182177
result = this.getInstruction(TryExceptGenerateOne())
@@ -196,10 +191,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
196191
tag = TryExceptCompareOneBranch() and
197192
kind instanceof TrueEdge and
198193
result = this.getTranslatedHandler().getFirstInstruction(any(GotoEdge edge))
199-
or
200-
// Unwind -> Parent
201-
tag = UnwindTag() and
202-
result = this.getParent().getChildSuccessor(this, kind)
203194
}
204195

205196
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -215,8 +206,6 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
215206

216207
override Instruction getALastInstructionInternal() {
217208
result = this.getTranslatedHandler().getALastInstruction()
218-
or
219-
result = this.getInstruction(UnwindTag())
220209
}
221210

222211
private TranslatedExpr getTranslatedCondition() {
@@ -236,6 +225,12 @@ class TranslatedMicrosoftTryExceptHandler extends TranslatedElement,
236225
}
237226

238227
final override Function getFunction() { result = tryExcept.getEnclosingFunction() }
228+
229+
override Instruction getExceptionSuccessorInstruction(EdgeKind kind) {
230+
// A throw from within a `__except` block flows to the handler for the parent of
231+
// the `__try`.
232+
result = this.getParent().getParent().getExceptionSuccessorInstruction(kind)
233+
}
239234
}
240235

241236
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
@@ -583,7 +578,7 @@ class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariab
583578
/**
584579
* A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement.
585580
*/
586-
private class TryOrMicrosoftTryStmt extends Stmt {
581+
class TryOrMicrosoftTryStmt extends Stmt {
587582
TryOrMicrosoftTryStmt() {
588583
this instanceof TryStmt or
589584
this instanceof MicrosoftTryStmt

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

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,41 +3167,45 @@ ir.c:
31673167
# 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2
31683168
# 36| m36_4(unknown) = ^CallSideEffect : ~m32_4
31693169
# 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4
3170-
#-----| Exception -> Block 3
3170+
#-----| Exception -> Block 4
31713171

3172-
# 39| Block 1
3172+
# 32| Block 1
3173+
# 32| v32_5(void) = Unwind :
3174+
# 32| v32_6(void) = AliasedUse : ~m40_5
3175+
# 32| v32_7(void) = ExitFunction :
3176+
3177+
# 39| Block 2
31733178
# 39| r39_1(int) = Constant[0] :
3174-
# 39| r39_2(bool) = CompareEQ : r38_2, r39_1
3179+
# 39| r39_2(bool) = CompareEQ : r38_1, r39_1
31753180
# 39| v39_3(void) = ConditionalBranch : r39_2
3176-
#-----| False (back edge) -> Block 2
3177-
#-----| True -> Block 5
3181+
#-----| False -> Block 3
3182+
#-----| True -> Block 6
31783183

3179-
# 39| Block 2
3184+
# 39| Block 3
31803185
# 39| r39_4(int) = Constant[1] :
3181-
# 39| r39_5(bool) = CompareEQ : r38_2, r39_4
3186+
# 39| r39_5(bool) = CompareEQ : r38_1, r39_4
31823187
# 39| v39_6(void) = ConditionalBranch : r39_5
3183-
#-----| False -> Block 5
3184-
#-----| True (back edge) -> Block 4
3185-
3186-
# 38| Block 3
3187-
# 38| m38_1(unknown) = Phi : from 0:~m36_5, from 4:~m40_5
3188-
# 38| r38_2(int) = Constant[1] :
3189-
# 39| r39_7(int) = Constant[-1] :
3190-
# 39| r39_8(bool) = CompareEQ : r38_2, r39_7
3191-
# 39| v39_9(void) = ConditionalBranch : r39_8
3192-
#-----| False (back edge) -> Block 1
3188+
#-----| False -> Block 6
31933189
#-----| True -> Block 5
31943190

3195-
# 40| Block 4
3191+
# 38| Block 4
3192+
# 38| r38_1(int) = Constant[1] :
3193+
# 39| r39_7(int) = Constant[-1] :
3194+
# 39| r39_8(bool) = CompareEQ : r38_1, r39_7
3195+
# 39| v39_9(void) = ConditionalBranch : r39_8
3196+
#-----| False -> Block 2
3197+
#-----| True -> Block 6
3198+
3199+
# 40| Block 5
31963200
# 40| r40_1(glval<unknown>) = FunctionAddress[ExRaiseAccessViolation] :
31973201
# 40| r40_2(int) = Constant[1] :
31983202
# 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2
3199-
# 40| m40_4(unknown) = ^CallSideEffect : ~m38_1
3200-
# 40| m40_5(unknown) = Chi : total:m38_1, partial:m40_4
3201-
#-----| Exception (back edge) -> Block 3
3203+
# 40| m40_4(unknown) = ^CallSideEffect : ~m36_5
3204+
# 40| m40_5(unknown) = Chi : total:m36_5, partial:m40_4
3205+
#-----| Exception -> Block 1
32023206

3203-
# 32| Block 5
3204-
# 32| v32_5(void) = Unreached :
3207+
# 32| Block 6
3208+
# 32| v32_8(void) = Unreached :
32053209

32063210
# 44| void try_with_finally()
32073211
# 44| Block 0
@@ -3261,6 +3265,12 @@ ir.c:
32613265
# 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2
32623266
# 81| m81_4(unknown) = ^CallSideEffect : ~m80_4
32633267
# 81| m81_5(unknown) = Chi : total:m80_4, partial:m81_4
3268+
#-----| Exception -> Block 1
3269+
3270+
# 80| Block 1
3271+
# 80| v80_5(void) = Unwind :
3272+
# 80| v80_6(void) = AliasedUse : ~m81_5
3273+
# 80| v80_7(void) = ExitFunction :
32643274

32653275
ir.cpp:
32663276
# 1| void Constants()

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

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,8 @@ sideEffectWithoutPrimary
88
instructionWithoutSuccessor
99
| 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() |
1010
| 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() |
11-
| ir.c:81:3:81:24 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:80:6:80:27 | void raise_access_violation() | void raise_access_violation() |
1211
ambiguousSuccessors
1312
unexplainedLoop
14-
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
15-
| ir.c:38:13:38:37 | Phi: 1 | Instruction 'Phi: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
16-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
17-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
18-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
19-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
20-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
21-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
22-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
23-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
24-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
25-
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
26-
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
27-
| ir.c:40:5:40:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
28-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
29-
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
3013
unnecessaryPhiInstruction
3114
memoryOperandDefinitionIsUnmodeled
3215
operandAcrossFunctions
@@ -37,9 +20,6 @@ containsLoopOfForwardEdges
3720
missingIRType
3821
multipleIRTypes
3922
lostReachability
40-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
41-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
42-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
4323
backEdgeCountMismatch
4424
useNotDominatedByDefinition
4525
switchInstructionWithoutDefaultEdge

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

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,8 @@ sideEffectWithoutPrimary
88
instructionWithoutSuccessor
99
| 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() |
1010
| 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() |
11-
| ir.c:81:3:81:24 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' has no successors in function '$@'. | ir.c:80:6:80:27 | void raise_access_violation() | void raise_access_violation() |
1211
ambiguousSuccessors
1312
unexplainedLoop
14-
| ir.c:38:13:38:37 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
15-
| ir.c:38:13:38:37 | Phi: 1 | Instruction 'Phi: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
16-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
17-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
18-
| ir.c:39:3:41:3 | CompareEQ: { ... } | Instruction 'CompareEQ: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
19-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
20-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
21-
| ir.c:39:3:41:3 | ConditionalBranch: { ... } | Instruction 'ConditionalBranch: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
22-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
23-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
24-
| ir.c:39:3:41:3 | Constant: { ... } | Instruction 'Constant: { ... }' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
25-
| ir.c:40:5:40:26 | Call: call to ExRaiseAccessViolation | Instruction 'Call: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
26-
| ir.c:40:5:40:26 | CallSideEffect: call to ExRaiseAccessViolation | Instruction 'CallSideEffect: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
27-
| ir.c:40:5:40:26 | Chi: call to ExRaiseAccessViolation | Instruction 'Chi: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
28-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Instruction 'FunctionAddress: call to ExRaiseAccessViolation' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
29-
| ir.c:40:28:40:28 | Constant: 1 | Instruction 'Constant: 1' is part of an unexplained loop in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
3013
unnecessaryPhiInstruction
3114
memoryOperandDefinitionIsUnmodeled
3215
operandAcrossFunctions
@@ -37,9 +20,6 @@ containsLoopOfForwardEdges
3720
missingIRType
3821
multipleIRTypes
3922
lostReachability
40-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
41-
| ir.c:39:3:41:3 | Constant: { ... } | Block 'Constant: { ... }' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
42-
| ir.c:40:5:40:26 | FunctionAddress: call to ExRaiseAccessViolation | Block 'FunctionAddress: call to ExRaiseAccessViolation' is not reachable by traversing only forward edges in function '$@'. | ir.c:32:6:32:32 | void unexplained_loop_regression() | void unexplained_loop_regression() |
4323
backEdgeCountMismatch
4424
useNotDominatedByDefinition
4525
switchInstructionWithoutDefaultEdge

0 commit comments

Comments
 (0)