Skip to content

Commit 31039e3

Browse files
committed
RULE-18-5-2: Improve macro defined results
Make the results easier to understand by reporting calls in macro expansions in the macros themselves, if they are defined by the developers of this project.
1 parent 102703a commit 31039e3

File tree

4 files changed

+86
-45
lines changed

4 files changed

+86
-45
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Used for RULE-18-5-2 for library aborts
2+
#include <cstdlib>
3+
#define LIBRARY_ABORT() std::abort()

cpp/misra/src/rules/RULE-18-5-2/AvoidProgramTerminatingFunctions.ql

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import cpp
1717
import codingstandards.cpp.misra
18+
import codingstandards.cpp.AlertReporting
1819

1920
predicate isTerminatingFunction(Function f, string functionName) {
2021
functionName = f.getName() and
@@ -27,27 +28,46 @@ predicate isTerminatingFunction(Function f, string functionName) {
2728
)
2829
}
2930

30-
predicate isAssertMacroCall(FunctionCall call) {
31+
class TerminatingFunctionUse extends Expr {
32+
string action;
33+
string functionName;
34+
35+
TerminatingFunctionUse() {
36+
exists(Function f | isTerminatingFunction(f, functionName) |
37+
this.(FunctionCall).getTarget() = f and
38+
action = "Call to"
39+
or
40+
this.(FunctionAccess).getTarget() = f and
41+
action = "Address taken for"
42+
)
43+
}
44+
45+
string getFunctionName() { result = functionName }
46+
47+
string getAction() { result = action }
48+
49+
Element getPrimaryElement() {
50+
// If this is defined in a macro in the users source location, then report the macro
51+
// expansion, otherwise report the element itself. This ensures that we always report
52+
// the use of the terminating function, but combine usages when the macro is defined
53+
// by the user.
54+
exists(Element e | e = MacroUnwrapper<TerminatingFunctionUse>::unwrapElement(this) |
55+
if exists(e.getFile().getRelativePath()) then result = e else result = this
56+
)
57+
}
58+
}
59+
60+
predicate isInAssertMacroInvocation(TerminatingFunctionUse use) {
3161
exists(MacroInvocation mi |
3262
mi.getMacroName() = "assert" and
33-
mi.getAnExpandedElement() = call
63+
mi.getAnExpandedElement() = use
3464
)
3565
}
3666

37-
from Expr e, Function f, string functionName, string action
67+
from TerminatingFunctionUse use
3868
where
39-
not isExcluded(e, BannedAPIsPackage::avoidProgramTerminatingFunctionsQuery()) and
40-
isTerminatingFunction(f, functionName) and
41-
(
42-
// Direct function calls (excluding assert macro calls)
43-
e instanceof FunctionCall and
44-
f = e.(FunctionCall).getTarget() and
45-
not isAssertMacroCall(e) and
46-
action = "Call to"
47-
or
48-
// Function access
49-
e instanceof FunctionAccess and
50-
f = e.(FunctionAccess).getTarget() and
51-
action = "Address taken for"
52-
)
53-
select e, action + " program-terminating function '" + functionName + "'."
69+
not isExcluded(use, BannedAPIsPackage::avoidProgramTerminatingFunctionsQuery()) and
70+
// Exclude the uses in the assert macro
71+
not isInAssertMacroInvocation(use)
72+
select use.getPrimaryElement(),
73+
use.getAction() + " program-terminating function '" + use.getFunctionName() + "'."
Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
1-
| test.cpp:7:3:7:7 | call to abort | Call to program-terminating function 'abort'. |
2-
| test.cpp:8:3:8:6 | call to exit | Call to program-terminating function 'exit'. |
3-
| test.cpp:9:3:9:7 | call to _Exit | Call to program-terminating function '_Exit'. |
4-
| test.cpp:10:3:10:12 | call to quick_exit | Call to program-terminating function 'quick_exit'. |
5-
| test.cpp:15:3:15:12 | call to abort | Call to program-terminating function 'abort'. |
6-
| test.cpp:16:3:16:11 | call to exit | Call to program-terminating function 'exit'. |
7-
| test.cpp:17:3:17:12 | call to _Exit | Call to program-terminating function '_Exit'. |
8-
| test.cpp:18:3:18:17 | call to quick_exit | Call to program-terminating function 'quick_exit'. |
9-
| test.cpp:19:3:19:16 | call to terminate | Call to program-terminating function 'terminate'. |
10-
| test.cpp:24:14:24:18 | abort | Address taken for program-terminating function 'abort'. |
11-
| test.cpp:25:14:25:17 | exit | Address taken for program-terminating function 'exit'. |
12-
| test.cpp:26:14:26:18 | _Exit | Address taken for program-terminating function '_Exit'. |
13-
| test.cpp:27:14:27:23 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
14-
| test.cpp:28:14:28:23 | abort | Address taken for program-terminating function 'abort'. |
15-
| test.cpp:29:14:29:22 | exit | Address taken for program-terminating function 'exit'. |
16-
| test.cpp:30:14:30:23 | _Exit | Address taken for program-terminating function '_Exit'. |
17-
| test.cpp:31:14:31:28 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
18-
| test.cpp:32:14:32:27 | terminate | Address taken for program-terminating function 'terminate'. |
19-
| test.cpp:37:18:37:22 | abort | Address taken for program-terminating function 'abort'. |
20-
| test.cpp:38:21:38:24 | exit | Address taken for program-terminating function 'exit'. |
21-
| test.cpp:39:21:39:25 | _Exit | Address taken for program-terminating function '_Exit'. |
22-
| test.cpp:40:21:40:30 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
23-
| test.cpp:41:18:41:27 | abort | Address taken for program-terminating function 'abort'. |
24-
| test.cpp:42:21:42:29 | exit | Address taken for program-terminating function 'exit'. |
25-
| test.cpp:43:21:43:30 | _Exit | Address taken for program-terminating function '_Exit'. |
26-
| test.cpp:44:21:44:35 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
27-
| test.cpp:45:18:45:31 | terminate | Address taken for program-terminating function 'terminate'. |
1+
| test.cpp:8:3:8:7 | call to abort | Call to program-terminating function 'abort'. |
2+
| test.cpp:9:3:9:6 | call to exit | Call to program-terminating function 'exit'. |
3+
| test.cpp:10:3:10:7 | call to _Exit | Call to program-terminating function '_Exit'. |
4+
| test.cpp:11:3:11:12 | call to quick_exit | Call to program-terminating function 'quick_exit'. |
5+
| test.cpp:16:3:16:12 | call to abort | Call to program-terminating function 'abort'. |
6+
| test.cpp:17:3:17:11 | call to exit | Call to program-terminating function 'exit'. |
7+
| test.cpp:18:3:18:12 | call to _Exit | Call to program-terminating function '_Exit'. |
8+
| test.cpp:19:3:19:17 | call to quick_exit | Call to program-terminating function 'quick_exit'. |
9+
| test.cpp:20:3:20:16 | call to terminate | Call to program-terminating function 'terminate'. |
10+
| test.cpp:25:14:25:18 | abort | Address taken for program-terminating function 'abort'. |
11+
| test.cpp:26:14:26:17 | exit | Address taken for program-terminating function 'exit'. |
12+
| test.cpp:27:14:27:18 | _Exit | Address taken for program-terminating function '_Exit'. |
13+
| test.cpp:28:14:28:23 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
14+
| test.cpp:29:14:29:23 | abort | Address taken for program-terminating function 'abort'. |
15+
| test.cpp:30:14:30:22 | exit | Address taken for program-terminating function 'exit'. |
16+
| test.cpp:31:14:31:23 | _Exit | Address taken for program-terminating function '_Exit'. |
17+
| test.cpp:32:14:32:28 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
18+
| test.cpp:33:14:33:27 | terminate | Address taken for program-terminating function 'terminate'. |
19+
| test.cpp:38:18:38:22 | abort | Address taken for program-terminating function 'abort'. |
20+
| test.cpp:39:21:39:24 | exit | Address taken for program-terminating function 'exit'. |
21+
| test.cpp:40:21:40:25 | _Exit | Address taken for program-terminating function '_Exit'. |
22+
| test.cpp:41:21:41:30 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
23+
| test.cpp:42:18:42:27 | abort | Address taken for program-terminating function 'abort'. |
24+
| test.cpp:43:21:43:29 | exit | Address taken for program-terminating function 'exit'. |
25+
| test.cpp:44:21:44:30 | _Exit | Address taken for program-terminating function '_Exit'. |
26+
| test.cpp:45:21:45:35 | quick_exit | Address taken for program-terminating function 'quick_exit'. |
27+
| test.cpp:46:18:46:31 | terminate | Address taken for program-terminating function 'terminate'. |
28+
| test.cpp:68:1:68:33 | #define CALL_ABORT() std::abort() | Call to program-terminating function 'abort'. |
29+
| test.cpp:69:1:69:33 | #define CALL_EXIT(x) std::exit(x) | Call to program-terminating function 'exit'. |
30+
| test.cpp:70:1:70:41 | #define CALL_TERMINATE() std::terminate() | Call to program-terminating function 'terminate'. |
31+
| test.cpp:77:3:77:17 | call to abort | Call to program-terminating function 'abort'. |

cpp/misra/test/rules/RULE-18-5-2/test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "custom_abort.h"
12
#include <cassert>
23
#include <cstdlib>
34
#include <stdexcept>
@@ -62,4 +63,17 @@ void test_compliant_alternatives() {
6263

6364
// Using exceptions for error handling
6465
throw std::runtime_error("error"); // COMPLIANT
66+
}
67+
68+
#define CALL_ABORT() std::abort() // NON_COMPLIANT
69+
#define CALL_EXIT(x) std::exit(x) // NON_COMPLIANT
70+
#define CALL_TERMINATE() std::terminate() // NON_COMPLIANT
71+
72+
void test_macro_expansion_with_terminating_functions() {
73+
// Macro expansions containing terminating functions
74+
CALL_ABORT(); // reported at the definition site
75+
CALL_EXIT(1); // reported at the definition site
76+
CALL_TERMINATE(); // reported at the definition site
77+
LIBRARY_ABORT(); // NON_COMPLIANT - macro not defined by user, so flagged at
78+
// the call site
6579
}

0 commit comments

Comments
 (0)