Skip to content

Commit e26f32a

Browse files
committed
Rule 21.10.2 - NoCsetjmpHeader.ql
New query to detect banned uses of the csetjmp header. [a]
1 parent 8485924 commit e26f32a

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @id cpp/misra/no-csetjmp-header
3+
* @name RULE-21-10-2: The standard header file <csetjmp> shall not be used
4+
* @description Using facilities from the <csetjmp> header causes undefined behavior by bypassing
5+
* normal function return mechanisms and may result in non-trivial object destruction
6+
* being omitted.
7+
* @kind problem
8+
* @precision very-high
9+
* @problem.severity error
10+
* @tags external/misra/id/rule-21-10-2
11+
* scope/single-translation-unit
12+
* external/misra/enforcement/decidable
13+
* external/misra/obligation/required
14+
*/
15+
16+
import cpp
17+
import codingstandards.cpp.misra
18+
import codingstandards.cpp.BannedFunctions
19+
20+
class CSetJmpHeader extends Include {
21+
CSetJmpHeader() { this.getIncludeText().regexpMatch("[<\\\"](csetjmp|setjmp.h)[>\\\"]") }
22+
}
23+
24+
class JmpBufVariable extends Variable {
25+
JmpBufVariable() { this.getType().(UserType).hasGlobalOrStdName("jmp_buf") }
26+
}
27+
28+
class LongjmpFunction extends Function {
29+
LongjmpFunction() { this.hasGlobalOrStdName("longjmp") }
30+
}
31+
32+
class SetjmpMacroInvocation extends MacroInvocation {
33+
SetjmpMacroInvocation() { this.getMacroName() = "setjmp" }
34+
}
35+
36+
from Element element, string message
37+
where
38+
not isExcluded(element, BannedAPIsPackage::noCsetjmpHeaderQuery()) and
39+
(
40+
message = "Use of banned header " + element.(CSetJmpHeader).getIncludeText() + "."
41+
or
42+
message =
43+
"Declaration of variable '" + element.(JmpBufVariable).getName() +
44+
"' with banned type 'jmp_buf'."
45+
or
46+
message =
47+
element.(BannedFunctions<LongjmpFunction>::Use).getAction() + " banned function '" +
48+
element.(BannedFunctions<LongjmpFunction>::Use).getFunctionName() + "'."
49+
or
50+
element instanceof SetjmpMacroInvocation and
51+
message = "Use of banned macro 'setjmp'."
52+
)
53+
select element, message
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
| test.cpp:1:1:1:18 | #include "csetjmp" | Use of banned header "csetjmp". |
2+
| test.cpp:2:1:2:19 | #include "setjmp.h" | Use of banned header "setjmp.h". |
3+
| test.cpp:3:1:3:18 | #include <csetjmp> | Use of banned header <csetjmp>. |
4+
| test.cpp:4:1:4:19 | #include <setjmp.h> | Use of banned header <setjmp.h>. |
5+
| test.cpp:8:9:8:10 | g1 | Declaration of variable 'g1' with banned type 'jmp_buf'. |
6+
| test.cpp:9:14:9:15 | g2 | Declaration of variable 'g2' with banned type 'jmp_buf'. |
7+
| test.cpp:12:11:12:12 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. |
8+
| test.cpp:13:7:13:16 | setjmp(env) | Use of banned macro 'setjmp'. |
9+
| test.cpp:14:5:14:11 | call to longjmp | Call to banned function 'longjmp'. |
10+
| test.cpp:19:16:19:17 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. |
11+
| test.cpp:20:7:20:16 | setjmp(env) | Use of banned macro 'setjmp'. |
12+
| test.cpp:21:5:21:16 | call to longjmp | Call to banned function 'longjmp'. |
13+
| test.cpp:26:11:26:12 | l1 | Declaration of variable 'l1' with banned type 'jmp_buf'. |
14+
| test.cpp:27:16:27:17 | l2 | Declaration of variable 'l2' with banned type 'jmp_buf'. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-21-10-2/NoCsetjmpHeader.ql
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include "csetjmp" // NON_COMPLIANT
2+
#include "setjmp.h" // NON_COMPLIANT
3+
#include <csetjmp> // NON_COMPLIANT
4+
#include <setjmp.h> // NON_COMPLIANT
5+
#include <stdexcept>
6+
7+
// Global variables for testing
8+
jmp_buf g1; // NON_COMPLIANT
9+
std::jmp_buf g2; // NON_COMPLIANT
10+
11+
void test_setjmp_usage() {
12+
jmp_buf l1; // NON_COMPLIANT
13+
if (setjmp(l1) == 0) { // NON_COMPLIANT
14+
longjmp(l1, 1); // NON_COMPLIANT
15+
}
16+
}
17+
18+
void test_std_setjmp_usage() {
19+
std::jmp_buf l1; // NON_COMPLIANT
20+
if (setjmp(l1) == 0) { // NON_COMPLIANT
21+
std::longjmp(l1, 1); // NON_COMPLIANT
22+
}
23+
}
24+
25+
void test_jmp_buf_declaration() {
26+
jmp_buf l1; // NON_COMPLIANT
27+
std::jmp_buf l2; // NON_COMPLIANT
28+
}
29+
30+
void test_compliant_alternative() {
31+
// Using structured exception handling or other alternatives
32+
// instead of setjmp/longjmp
33+
try {
34+
throw std::runtime_error("error");
35+
} catch (const std::runtime_error &) { // COMPLIANT
36+
// Handle error properly
37+
}
38+
}

0 commit comments

Comments
 (0)