Skip to content

Commit 3d9d9fe

Browse files
authored
Merge pull request #19746 from jketema/seh
C++: Use SEH exception edges in IR and generate SEH exception edges for calls in `__try` blocks
2 parents fb0f12b + 1b2813d commit 3d9d9fe

File tree

11 files changed

+577
-232
lines changed

11 files changed

+577
-232
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* The `ThrowingFunction` class (`semmle.code.cpp.models.interfaces.Throwing`) has been deprecated. Please use the `AlwaysSehThrowingFunction` class instead.

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

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,10 @@ abstract class TranslatedCall extends TranslatedExpr {
8484
this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction()
8585
)
8686
else (
87-
not this.mustThrowException() and
87+
not this.mustThrowException(_) and
8888
result = this.getParent().getChildSuccessor(this, kind)
8989
or
90-
this.mayThrowException() and
91-
kind instanceof CppExceptionEdge and
90+
this.mayThrowException(kind) and
9291
result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge))
9392
)
9493
}
@@ -117,14 +116,14 @@ abstract class TranslatedCall extends TranslatedExpr {
117116
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
118117

119118
/**
120-
* Holds if the evaluation of this call may throw an exception.
119+
* Holds if the evaluation of this call may throw an exception of the kind represented by the `ExceptionEdge`.
121120
*/
122-
abstract predicate mayThrowException();
121+
abstract predicate mayThrowException(ExceptionEdge e);
123122

124123
/**
125-
* Holds if the evaluation of this call always throws an exception.
124+
* Holds if the evaluation of this call always throws an exception of the kind represented by the `ExceptionEdge`.
126125
*/
127-
abstract predicate mustThrowException();
126+
abstract predicate mustThrowException(ExceptionEdge e);
128127

129128
/**
130129
* Gets the result type of the call.
@@ -332,14 +331,14 @@ class TranslatedExprCall extends TranslatedCallExpr {
332331
result = getTranslatedExpr(expr.getExpr().getFullyConverted())
333332
}
334333

335-
final override predicate mayThrowException() {
334+
final override predicate mayThrowException(ExceptionEdge e) {
336335
// We assume that a call to a function pointer will not throw an exception.
337336
// This is not sound in general, but this will greatly reduce the number of
338337
// exceptional edges.
339338
none()
340339
}
341340

342-
final override predicate mustThrowException() { none() }
341+
final override predicate mustThrowException(ExceptionEdge e) { none() }
343342
}
344343

345344
/**
@@ -362,16 +361,16 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
362361
not exists(MemberFunction func | expr.getTarget() = func and func.isStatic())
363362
}
364363

365-
final override predicate mayThrowException() {
366-
expr.getTarget().(ThrowingFunction).mayThrowException(_)
364+
final override predicate mayThrowException(ExceptionEdge e) {
365+
this.mustThrowException(e)
367366
or
368-
expr.getTarget() instanceof AlwaysSehThrowingFunction
367+
exists(MicrosoftTryStmt tryStmt | tryStmt.getStmt() = expr.getEnclosingStmt().getParent*()) and
368+
e instanceof SehExceptionEdge
369369
}
370370

371-
final override predicate mustThrowException() {
372-
expr.getTarget().(ThrowingFunction).mayThrowException(true)
373-
or
374-
expr.getTarget() instanceof AlwaysSehThrowingFunction
371+
final override predicate mustThrowException(ExceptionEdge e) {
372+
expr.getTarget() instanceof AlwaysSehThrowingFunction and
373+
e instanceof SehExceptionEdge
375374
}
376375
}
377376

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,14 +2483,14 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
24832483
result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index).getFullyConverted())
24842484
}
24852485

2486-
final override predicate mayThrowException() {
2486+
final override predicate mayThrowException(ExceptionEdge e) {
24872487
// We assume that a call to `new` or `new[]` will never throw. This is not
24882488
// sound in general, but this will greatly reduce the number of exceptional
24892489
// edges.
24902490
none()
24912491
}
24922492

2493-
final override predicate mustThrowException() { none() }
2493+
final override predicate mustThrowException(ExceptionEdge e) { none() }
24942494
}
24952495

24962496
TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) {
@@ -2556,14 +2556,14 @@ class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, Trans
25562556
result = getTranslatedExpr(expr.getExprWithReuse().getFullyConverted())
25572557
}
25582558

2559-
final override predicate mayThrowException() {
2559+
final override predicate mayThrowException(ExceptionEdge e) {
25602560
// We assume that a call to `delete` or `delete[]` will never throw. This is not
25612561
// sound in general, but this will greatly reduce the number of exceptional
25622562
// edges.
25632563
none()
25642564
}
25652565

2566-
final override predicate mustThrowException() { none() }
2566+
final override predicate mustThrowException(ExceptionEdge e) { none() }
25672567
}
25682568

25692569
TranslatedDeleteOrDeleteArrayExpr getTranslatedDeleteOrDeleteArray(DeleteOrDeleteArrayExpr newExpr) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
214214
exists(ThrowExpr throw | throw.getEnclosingFunction() = func)
215215
or
216216
exists(FunctionCall call | call.getEnclosingFunction() = func |
217-
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException()
217+
getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException(_)
218218
)
219219
)
220220
or

cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
1212

1313
/**
1414
* A function that is known to raise an exception.
15+
*
16+
* DEPRECATED: use `AlwaysSehThrowingFunction` instead.
1517
*/
16-
abstract class ThrowingFunction extends Function {
18+
abstract deprecated class ThrowingFunction extends Function {
1719
/**
1820
* Holds if this function may throw an exception during evaluation.
1921
* If `unconditional` is `true` the function always throws an exception.

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49652,6 +49652,43 @@ try_except.c:
4965249652
# 40| Type = [IntType] int
4965349653
# 40| ValueCategory = prvalue(load)
4965449654
# 42| getStmt(2): [ReturnStmt] return ...
49655+
# 44| [TopLevelFunction] int i()
49656+
# 44| <params>:
49657+
# 46| [TopLevelFunction] void j(int)
49658+
# 46| <params>:
49659+
# 46| getParameter(0): [Parameter] b
49660+
# 46| Type = [IntType] int
49661+
# 46| getEntryPoint(): [BlockStmt] { ... }
49662+
# 47| getStmt(0): [DeclStmt] declaration
49663+
# 47| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
49664+
# 47| Type = [IntType] int
49665+
# 47| getVariable().getInitializer(): [Initializer] initializer for x
49666+
# 47| getExpr(): [Literal] 0
49667+
# 47| Type = [IntType] int
49668+
# 47| Value = [Literal] 0
49669+
# 47| ValueCategory = prvalue
49670+
# 48| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... }
49671+
# 48| getStmt(): [BlockStmt] { ... }
49672+
# 49| getStmt(0): [DeclStmt] declaration
49673+
# 49| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
49674+
# 49| Type = [IntType] int
49675+
# 49| getVariable().getInitializer(): [Initializer] initializer for y
49676+
# 49| getExpr(): [FunctionCall] call to i
49677+
# 49| Type = [IntType] int
49678+
# 49| ValueCategory = prvalue
49679+
# 51| getCondition(): [Literal] 1
49680+
# 51| Type = [IntType] int
49681+
# 51| Value = [Literal] 1
49682+
# 51| ValueCategory = prvalue
49683+
# 51| getExcept(): [BlockStmt] { ... }
49684+
# 52| getStmt(0): [ExprStmt] ExprStmt
49685+
# 52| getExpr(): [FunctionCall] call to sink
49686+
# 52| Type = [VoidType] void
49687+
# 52| ValueCategory = prvalue
49688+
# 52| getArgument(0): [VariableAccess] x
49689+
# 52| Type = [IntType] int
49690+
# 52| ValueCategory = prvalue(load)
49691+
# 54| getStmt(2): [ReturnStmt] return ...
4965549692
try_except.cpp:
4965649693
# 3| [TopLevelFunction] void ProbeFunction()
4965749694
# 3| <params>:

0 commit comments

Comments
 (0)