Skip to content

Commit 28afda1

Browse files
committed
Shared CFG: add callableExitStep hook for routing epilogue tails to exit nodes
1 parent db8b2cf commit 28afda1

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

‎shared/controlflow/codeql/controlflow/ControlFlowGraph.qll‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,23 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
11891189
none()
11901190
}
11911191

1192+
/**
1193+
* Holds if `n` steps directly to the normal exit node (`normal = true`)
1194+
* or the exceptional exit node (`normal = false`) of callable `c`.
1195+
*
1196+
* By default the only node that reaches a callable's normal exit is the
1197+
* "after" node of its body. This predicate lets a language route the tail
1198+
* of a function epilogue (such as Go's result-read or deferred-call nodes)
1199+
* to the appropriate exit node, which is useful when the body cannot
1200+
* terminate normally (e.g. it always ends in a `return`) and therefore has
1201+
* no "after" node to anchor the epilogue on.
1202+
*
1203+
* The default implementation adds no such steps.
1204+
*/
1205+
default predicate callableExitStep(PreControlFlowNode n, Callable c, boolean normal) {
1206+
none()
1207+
}
1208+
11921209
/**
11931210
* Holds if there is a local non-abrupt step from `n1` to `n2`.
11941211
*
@@ -1464,6 +1481,12 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
14641481
n1.isAfter(getBodyExit(c)) and
14651482
n2.(NormalExitNodeImpl).getEnclosingCallable() = c
14661483
or
1484+
Input2::callableExitStep(n1, c, true) and
1485+
n2.(NormalExitNodeImpl).getEnclosingCallable() = c
1486+
or
1487+
Input2::callableExitStep(n1, c, false) and
1488+
n2.(ExceptionalExitNodeImpl).getEnclosingCallable() = c
1489+
or
14671490
n1.(AnnotatedExitNodeImpl).getEnclosingCallable() = c and
14681491
n2.(ExitNodeImpl).getEnclosingCallable() = c
14691492
)

0 commit comments

Comments
 (0)