Skip to content

Commit 46c3332

Browse files
committed
ENV32-C: exit functions can be macros
1 parent b461260 commit 46c3332

File tree

1 file changed

+27
-15
lines changed

1 file changed

+27
-15
lines changed

c/cert/src/rules/ENV32-C/ExitHandlersMustReturnNormally.ql

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,26 @@
1414
import cpp
1515
import codingstandards.c.cert
1616

17-
class ExitFunction extends Function {
18-
ExitFunction() { this.hasGlobalName(["_Exit", "exit", "quick_exit", "longjmp"]) }
17+
/**
18+
* Exit function or macro.
19+
*/
20+
class Exit extends Locatable {
21+
Exit() {
22+
["_Exit", "exit", "quick_exit", "longjmp"] = [this.(Function).getName(), this.(Macro).getName()]
23+
}
1924
}
2025

21-
class ExitFunctionCall extends FunctionCall {
22-
ExitFunctionCall() { this.getTarget() instanceof ExitFunction }
26+
class ExitExpr extends Expr {
27+
ExitExpr() {
28+
this.(FunctionCall).getTarget() instanceof Exit
29+
or
30+
any(MacroInvocation m | this = m.getExpr()).getMacro() instanceof Exit
31+
}
2332
}
2433

34+
/**
35+
* Functions that are registered as exit handlers.
36+
*/
2537
class RegisteredAtexit extends FunctionAccess {
2638
RegisteredAtexit() {
2739
exists(FunctionCall ae |
@@ -32,24 +44,26 @@ class RegisteredAtexit extends FunctionAccess {
3244
}
3345

3446
/**
35-
* Nodes of type Function, FunctionCall or FunctionAccess that \
36-
* are reachable from a redistered atexit handler and
47+
* Nodes of type Function, FunctionCall, FunctionAccess or ExitExpr
48+
* that are reachable from a registered atexit handler and
3749
* can reach an exit function.
3850
*/
3951
class InterestingNode extends ControlFlowNode {
4052
InterestingNode() {
4153
exists(Function f |
4254
(
4355
this = f and
44-
// exit functions are not part of edges
45-
not this = any(ExitFunction ec)
56+
// exit is not part of edges
57+
not this instanceof Exit
4658
or
4759
this.(FunctionCall).getTarget() = f
4860
or
4961
this.(FunctionAccess).getTarget() = f
62+
or
63+
this.(ExitExpr).getEnclosingFunction() = f
5064
) and
51-
// reaches an exit function
52-
f.calls*(any(ExitFunction e)) and
65+
// reaches an `ExitExpr`
66+
f.calls*(any(ExitExpr ee).getEnclosingFunction()) and
5367
// is reachable from a registered atexit function
5468
exists(RegisteredAtexit re | re.getTarget().calls*(f))
5569
)
@@ -62,14 +76,12 @@ class InterestingNode extends ControlFlowNode {
6276
* `Function` and `FunctionCall` in their body.
6377
*/
6478
query predicate edges(InterestingNode a, InterestingNode b) {
65-
a.(FunctionAccess).getTarget() = b
66-
or
67-
a.(FunctionCall).getTarget() = b
68-
or
79+
a.(FunctionAccess).getTarget() = b or
80+
a.(FunctionCall).getTarget() = b or
6981
a.(Function).calls(_, b)
7082
}
7183

72-
from RegisteredAtexit hr, Function f, ExitFunctionCall e
84+
from RegisteredAtexit hr, Function f, ExitExpr e
7385
where edges(hr, f) and edges+(f, e)
7486
select f, hr, e, "The function is $@ and $@. It must instead terminate by returning.", hr,
7587
"registered as `exit handler`", e, "calls an `exit function`"

0 commit comments

Comments
 (0)