Skip to content

Commit 104bdc7

Browse files
Implement Misra-c Noreturn rule package.
Covers rules 17-9 through 17-11, regarding the use of the _Noreturn attribute.
1 parent 9e73400 commit 104bdc7

15 files changed

+349
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* @id c/misra/non-void-return-type-of-noreturn-function
3+
* @name RULE-17-10: A function declared with _noreturn shall have a return type of void
4+
* @description Function declared with _noreturn will by definition not return a value, and should
5+
* be declared to return void.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity recommendation
9+
* @tags external/misra/id/rule-17-10
10+
* external/misra/obligation/required
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
16+
from Function f, Type returnType
17+
where
18+
not isExcluded(f, NoReturnPackage::nonVoidReturnTypeOfNoreturnFunctionQuery()) and
19+
f.getASpecifier().getName() = "noreturn" and
20+
returnType = f.getType() and
21+
not returnType instanceof VoidType
22+
select
23+
f, "The function " + f.getName() + " is declared _noreturn but has a return type of " + returnType.toString() + "."
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @id c/misra/function-with-no-returning-branch-should-be-noreturn
3+
* @name RULE-17-11: A function without a branch that returns shall be declared with _Noreturn
4+
* @description Functions which cannot return should be declared with _Noreturn.
5+
* @kind problem
6+
* @precision high
7+
* @problem.severity recommendation
8+
* @tags external/misra/id/rule-17-11
9+
* external/misra/obligation/advisory
10+
*/
11+
12+
import cpp
13+
import codingstandards.c.misra
14+
15+
from Function f
16+
where
17+
not isExcluded(f, NoReturnPackage::returnStatementInNoreturnFunctionQuery()) and
18+
not f.getASpecifier().getName() = "noreturn" and
19+
not exists(ReturnStmt s |
20+
f = s.getEnclosingFunction() and
21+
s.getBasicBlock().isReachable()
22+
)
23+
select
24+
f, "The function " + f.getName() + " cannot return and should be declared attribute _Noreturn."
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @id c/misra/return-statement-in-noreturn-function
3+
* @name RULE-17-9: Verify that a function declared with _Noreturn does not return
4+
* @description Returning inside a function declared with _Noreturn is undefined behavior.
5+
* @kind problem
6+
* @precision very-high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-17-9
9+
* external/misra/obligation/mandatory
10+
*/
11+
12+
import cpp
13+
import codingstandards.c.misra
14+
15+
from Function f
16+
where
17+
not isExcluded(f, NoReturnPackage::returnStatementInNoreturnFunctionQuery()) and
18+
f.getASpecifier().getName() = "noreturn" and
19+
exists(ReturnStmt s |
20+
f = s.getEnclosingFunction() and
21+
s.getBasicBlock().isReachable()
22+
)
23+
select
24+
f, "The function " + f.getName() + " declared with attribute _Noreturn returns a value."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
No expected results have yet been specified
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-17-10/NonVoidReturnTypeOfNoreturnFunction.ql

c/misra/test/rules/RULE-17-10/test.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "stdlib.h"
2+
3+
void f1(); // COMPLIANT
4+
int f2(); // COMPLIANT
5+
_Noreturn void f3(); // COMPLIANT
6+
_Noreturn int f4(); // NON-COMPLIANT
7+
8+
void f5() { // COMPLIANT
9+
}
10+
11+
int f6() { // COMPLIANT
12+
return 0;
13+
}
14+
15+
_Noreturn void f7() { // COMPLIANT
16+
abort();
17+
}
18+
19+
_Noreturn int f8() { // NON-COMPLIANT
20+
abort();
21+
return 0;
22+
}
23+
24+
_Noreturn void* f9(); // NON-COMPLIANT
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| test.c:7:6:7:21 | test_noreturn_f2 | The function test_noreturn_f2 cannot return and should be declared attribute _Noreturn. |
2+
| test.c:19:6:19:21 | test_noreturn_f4 | The function test_noreturn_f4 cannot return and should be declared attribute _Noreturn. |
3+
| test.c:48:6:48:21 | test_noreturn_f8 | The function test_noreturn_f8 cannot return and should be declared attribute _Noreturn. |
4+
| test.c:64:6:64:22 | test_noreturn_f10 | The function test_noreturn_f10 cannot return and should be declared attribute _Noreturn. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-17-11/FunctionWithNoReturningBranchShouldBeNoreturn.ql

c/misra/test/rules/RULE-17-11/test.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include "stdlib.h"
2+
3+
_Noreturn void test_noreturn_f1(int i) { // COMPLIANT
4+
abort();
5+
}
6+
7+
void test_noreturn_f2(int i) { // NON_COMPLIANT
8+
abort();
9+
}
10+
11+
12+
_Noreturn void test_noreturn_f3(int i) { // COMPLIANT
13+
if (i > 0) {
14+
abort();
15+
}
16+
exit(1);
17+
}
18+
19+
void test_noreturn_f4(int i) { // NON_COMPLIANT
20+
if (i > 0) {
21+
abort();
22+
}
23+
exit(1);
24+
}
25+
26+
void test_noreturn_f5(int i) { // COMPLIANT
27+
if (i > 0) {
28+
return;
29+
}
30+
exit(1);
31+
}
32+
33+
void test_noreturn_f6(int i) { // COMPLIANT
34+
if (i > 0) {
35+
abort();
36+
}
37+
if (i < 0) {
38+
abort();
39+
}
40+
}
41+
42+
void test_noreturn_f7(int i) { // COMPLIANT
43+
if (i > 0) {
44+
abort();
45+
}
46+
}
47+
48+
void test_noreturn_f8(int i) { // NON_COMPLIANT
49+
if (i > 0) {
50+
abort();
51+
} else {
52+
abort();
53+
}
54+
}
55+
56+
_Noreturn void test_noreturn_f9(int i) { // COMPLIANT
57+
if (i > 0) {
58+
abort();
59+
} else {
60+
abort();
61+
}
62+
}
63+
64+
void test_noreturn_f10(int i) { // NON_COMPLIANT
65+
if (i > 0) {
66+
abort();
67+
}
68+
while (1) {
69+
i = 5;
70+
}
71+
}
72+
73+
_Noreturn void test_noreturn_f11(int i) { // COMPLIANT
74+
if (i > 0) {
75+
abort();
76+
}
77+
while (1) {
78+
i = 5;
79+
}
80+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:7:16:7:31 | test_noreturn_f2 | The function test_noreturn_f2 declared with attribute _Noreturn returns a value. |
2+
| test.c:32:16:32:31 | test_noreturn_f5 | The function test_noreturn_f5 declared with attribute _Noreturn returns a value. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-17-9/ReturnStatementInNoreturnFunction.ql

c/misra/test/rules/RULE-17-9/test.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "stdlib.h"
2+
3+
_Noreturn void test_noreturn_f1(int i) { // COMPLIANT
4+
abort();
5+
}
6+
7+
_Noreturn void test_noreturn_f2(int i) { // NON_COMPLIANT
8+
if (i > 0) {
9+
abort();
10+
}
11+
if (i < 0) {
12+
abort();
13+
}
14+
}
15+
16+
_Noreturn void test_noreturn_f3(int i) { // COMPLIANT
17+
if (i > 0) {
18+
abort();
19+
}
20+
exit(1);
21+
}
22+
23+
void test_noreturn_f4(int i) { // COMPLIANT
24+
if (i > 0) {
25+
abort();
26+
}
27+
if (i < 0) {
28+
abort();
29+
}
30+
}
31+
32+
_Noreturn void test_noreturn_f5(int i) { // NON_COMPLIANT
33+
if (i > 0) {
34+
abort();
35+
}
36+
}
37+
38+
_Noreturn void test_noreturn_f6(int i) { // COMPLIANT
39+
if (i > 0) {
40+
abort();
41+
}
42+
while (1) {
43+
i = 5;
44+
}
45+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype NoReturnQuery =
7+
TNonVoidReturnTypeOfNoreturnFunctionQuery() or
8+
TFunctionWithNoReturningBranchShouldBeNoreturnQuery() or
9+
TReturnStatementInNoreturnFunctionQuery()
10+
11+
predicate isNoReturnQueryMetadata(Query query, string queryId, string ruleId, string category) {
12+
query =
13+
// `Query` instance for the `nonVoidReturnTypeOfNoreturnFunction` query
14+
NoReturnPackage::nonVoidReturnTypeOfNoreturnFunctionQuery() and
15+
queryId =
16+
// `@id` for the `nonVoidReturnTypeOfNoreturnFunction` query
17+
"c/misra/non-void-return-type-of-noreturn-function" and
18+
ruleId = "RULE-17-10" and
19+
category = "required"
20+
or
21+
query =
22+
// `Query` instance for the `functionWithNoReturningBranchShouldBeNoreturn` query
23+
NoReturnPackage::functionWithNoReturningBranchShouldBeNoreturnQuery() and
24+
queryId =
25+
// `@id` for the `functionWithNoReturningBranchShouldBeNoreturn` query
26+
"c/misra/function-with-no-returning-branch-should-be-noreturn" and
27+
ruleId = "RULE-17-11" and
28+
category = "advisory"
29+
or
30+
query =
31+
// `Query` instance for the `returnStatementInNoreturnFunction` query
32+
NoReturnPackage::returnStatementInNoreturnFunctionQuery() and
33+
queryId =
34+
// `@id` for the `returnStatementInNoreturnFunction` query
35+
"c/misra/return-statement-in-noreturn-function" and
36+
ruleId = "RULE-17-9" and
37+
category = "mandatory"
38+
}
39+
40+
module NoReturnPackage {
41+
Query nonVoidReturnTypeOfNoreturnFunctionQuery() {
42+
//autogenerate `Query` type
43+
result =
44+
// `Query` type for `nonVoidReturnTypeOfNoreturnFunction` query
45+
TQueryC(TNoReturnPackageQuery(TNonVoidReturnTypeOfNoreturnFunctionQuery()))
46+
}
47+
48+
Query functionWithNoReturningBranchShouldBeNoreturnQuery() {
49+
//autogenerate `Query` type
50+
result =
51+
// `Query` type for `functionWithNoReturningBranchShouldBeNoreturn` query
52+
TQueryC(TNoReturnPackageQuery(TFunctionWithNoReturningBranchShouldBeNoreturnQuery()))
53+
}
54+
55+
Query returnStatementInNoreturnFunctionQuery() {
56+
//autogenerate `Query` type
57+
result =
58+
// `Query` type for `returnStatementInNoreturnFunction` query
59+
TQueryC(TNoReturnPackageQuery(TReturnStatementInNoreturnFunctionQuery()))
60+
}
61+
}

cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import Memory1
4242
import Memory2
4343
import Memory3
4444
import Misc
45+
import NoReturn
4546
import OutOfBounds
4647
import Pointers1
4748
import Pointers2
@@ -113,6 +114,7 @@ newtype TCQuery =
113114
TMemory2PackageQuery(Memory2Query q) or
114115
TMemory3PackageQuery(Memory3Query q) or
115116
TMiscPackageQuery(MiscQuery q) or
117+
TNoReturnPackageQuery(NoReturnQuery q) or
116118
TOutOfBoundsPackageQuery(OutOfBoundsQuery q) or
117119
TPointers1PackageQuery(Pointers1Query q) or
118120
TPointers2PackageQuery(Pointers2Query q) or
@@ -184,6 +186,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
184186
isMemory2QueryMetadata(query, queryId, ruleId, category) or
185187
isMemory3QueryMetadata(query, queryId, ruleId, category) or
186188
isMiscQueryMetadata(query, queryId, ruleId, category) or
189+
isNoReturnQueryMetadata(query, queryId, ruleId, category) or
187190
isOutOfBoundsQueryMetadata(query, queryId, ruleId, category) or
188191
isPointers1QueryMetadata(query, queryId, ruleId, category) or
189192
isPointers2QueryMetadata(query, queryId, ruleId, category) or

rule_packages/c/NoReturn.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"MISRA-C-2012": {
3+
"RULE-17-10": {
4+
"properties": {
5+
"obligation": "required"
6+
},
7+
"queries": [
8+
{
9+
"description": "Function declared with _noreturn will by definition not return a value, and should be declared to return void.",
10+
"kind": "problem",
11+
"name": "A function declared with _noreturn shall have a return type of void",
12+
"precision": "very-high",
13+
"severity": "recommendation",
14+
"short_name": "NonVoidReturnTypeOfNoreturnFunction",
15+
"tags": []
16+
}
17+
],
18+
"title": "A function declared with _noreturn shall have a return type of void"
19+
},
20+
"RULE-17-11": {
21+
"properties": {
22+
"obligation": "advisory"
23+
},
24+
"queries": [
25+
{
26+
"description": "Functions which cannot return should be declared with _Noreturn.",
27+
"kind": "problem",
28+
"name": "A function without a branch that returns shall be declared with _Noreturn",
29+
"precision": "high",
30+
"severity": "recommendation",
31+
"short_name": "FunctionWithNoReturningBranchShouldBeNoreturn",
32+
"tags": []
33+
}
34+
],
35+
"title": "A function without a branch that returns shall be declared with _Noreturn"
36+
},
37+
"RULE-17-9": {
38+
"properties": {
39+
"obligation": "mandatory"
40+
},
41+
"queries": [
42+
{
43+
"description": "Returning inside a function declared with _Noreturn is undefined behavior.",
44+
"kind": "problem",
45+
"name": "Verify that a function declared with _Noreturn does not return",
46+
"precision": "very-high",
47+
"severity": "error",
48+
"short_name": "ReturnStatementInNoreturnFunction",
49+
"tags": []
50+
}
51+
],
52+
"title": "Verify that a function declared with _Noreturn does not return"
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)