Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 130c264

Browse filesBrowse files
authored
Merge pull request #719 from github/michaelrfairhurst/implement-function-types-package
Implement function types package
2 parents 228b671 + c972403 commit 130c264
Copy full SHA for 130c264

File tree

Expand file treeCollapse file tree

9 files changed

+209
-2
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+209
-2
lines changed
+33Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @id c/misra/function-addresses-should-address-operator
3+
* @name RULE-17-12: A function identifier should only be called with a parenthesized parameter list or used with a &
4+
* @description A function identifier should only be called with a parenthesized parameter list or
5+
* used with a & (address-of).
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity error
9+
* @tags external/misra/id/rule-17-12
10+
* readability
11+
* external/misra/c/2012/amendment3
12+
* external/misra/obligation/advisory
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.misra
17+
18+
predicate isImplicitlyAddressed(FunctionAccess access) {
19+
not access.getParent() instanceof AddressOfExpr and
20+
// Note: the following *seems* to only exist in c++ codebases, for instance,
21+
// when calling a member. In c, this syntax should always extract as a
22+
// [FunctionCall] rather than a [ExprCall] of a [FunctionAccess]. Still, this
23+
// is a good pattern to be defensive against.
24+
not exists(ExprCall call | call.getExpr() = access)
25+
}
26+
27+
from FunctionAccess funcAccess
28+
where
29+
not isExcluded(funcAccess, FunctionTypesPackage::functionAddressesShouldAddressOperatorQuery()) and
30+
isImplicitlyAddressed(funcAccess)
31+
select funcAccess,
32+
"The address of function " + funcAccess.getTarget().getName() +
33+
" is taken without the & operator."
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
| test.c:14:25:14:29 | func2 | The address of function func2 is taken without the & operator. |
2+
| test.c:15:25:15:29 | func3 | The address of function func3 is taken without the & operator. |
3+
| test.c:21:12:21:16 | func1 | The address of function func1 is taken without the & operator. |
4+
| test.c:38:3:38:7 | func1 | The address of function func1 is taken without the & operator. |
5+
| test.c:39:3:39:7 | func2 | The address of function func2 is taken without the & operator. |
6+
| test.c:57:13:57:17 | func1 | The address of function func1 is taken without the & operator. |
7+
| test.c:58:21:58:25 | func2 | The address of function func2 is taken without the & operator. |
8+
| test.c:59:13:59:17 | func1 | The address of function func1 is taken without the & operator. |
9+
| test.c:59:20:59:24 | func2 | The address of function func2 is taken without the & operator. |
10+
| test.c:67:11:67:15 | func1 | The address of function func1 is taken without the & operator. |
11+
| test.c:68:12:68:16 | func1 | The address of function func1 is taken without the & operator. |
12+
| test.c:69:12:69:16 | func1 | The address of function func1 is taken without the & operator. |
13+
| test.c:71:18:71:22 | func1 | The address of function func1 is taken without the & operator. |
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-17-12/FunctionAddressesShouldAddressOperator.ql

‎c/misra/test/rules/RULE-17-12/test.c

Copy file name to clipboard
+107Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
void func1() {}
2+
void func2(int x, char *y) {}
3+
4+
typedef struct {
5+
} s;
6+
7+
int func3() { return 0; }
8+
9+
typedef void (*func_ptr_t1)();
10+
typedef void (*func_ptr_t2)(int x, char *y);
11+
typedef s (*func_ptr_t3)();
12+
13+
func_ptr_t1 func_ptr1 = &func1; // COMPLIANT
14+
func_ptr_t2 func_ptr2 = func2; // NON-COMPLIANT
15+
func_ptr_t3 func_ptr3 = func3 + 0; // NON-COMPLIANT
16+
17+
void take_func(func_ptr_t1 f1, func_ptr_t2 f2);
18+
19+
func_ptr_t1 returns_func(int x) {
20+
if (x == 0) {
21+
return func1; // NON-COMPLIANT
22+
} else if (x == 1) {
23+
return &func1; // COMPLIANT
24+
}
25+
26+
return returns_func(0); // COMPLIANT
27+
}
28+
29+
#define MACRO_IDENTITY(f) (f)
30+
#define MACRO_INVOKE_RISKY(f) (f())
31+
#define MACRO_INVOKE_IMPROVED(f) ((f)())
32+
#define MACRO_INVOKE_AND_USE_AS_TOKEN(f) f(0, #f)
33+
34+
void test() {
35+
func1(); // COMPLIANT
36+
func2(1, "hello"); // COMPLIANT
37+
38+
func1; // NON-COMPLIANT
39+
func2; // NON-COMPLIANT
40+
41+
&func1; // COMPLIANT
42+
&func2; // COMPLIANT
43+
44+
(func1)(); // COMPLIANT
45+
(func2)(1, "hello"); // COMPLIANT
46+
47+
&(func1); // COMPLIANT
48+
&(func2); // COMPLIANT
49+
50+
(&func1)(); // COMPLIANT
51+
(&func2)(1, "hello"); // COMPLIANT
52+
53+
(func1()); // COMPLIANT
54+
(func2(1, "hello")); // COMPLIANT
55+
56+
take_func(&func1, &func2); // COMPLIANT
57+
take_func(func1, &func2); // NON-COMPLIANT
58+
take_func(&func1, func2); // NON-COMPLIANT
59+
take_func(func1, func2); // NON-COMPLIANT
60+
61+
returns_func(0); // COMPLIANT
62+
returns_func(0)(); // COMPLIANT
63+
(returns_func(0))(); // COMPLIANT
64+
65+
(void *)&func1; // COMPLIANT
66+
(void *)(&func1); // COMPLIANT
67+
(void *)func1; // NON-COMPLIANT
68+
(void *)(func1); // NON-COMPLIANT
69+
((void *)func1); // NON-COMPLIANT
70+
71+
MACRO_IDENTITY(func1); // NON-COMPLIANT
72+
MACRO_IDENTITY(func1)(); // NON-COMPLIANT[FALSE NEGATIVE]
73+
MACRO_IDENTITY(&func1); // COMPLIANT
74+
MACRO_IDENTITY (&func1)(); // COMPLIANT
75+
76+
MACRO_INVOKE_RISKY(func3); // NON-COMPLIANT[FALSE NEGATIVE]
77+
MACRO_INVOKE_IMPROVED(func3); // NON-COMPLIANT[FALSE NEGATIVE]
78+
MACRO_INVOKE_IMPROVED(&func3); // COMPLIANT
79+
80+
MACRO_INVOKE_AND_USE_AS_TOKEN(func1); // COMPLIANT
81+
82+
// Function pointers are exempt from this rule.
83+
func_ptr1(); // COMPLIANT
84+
func_ptr2(1, "hello"); // COMPLIANT
85+
func_ptr1; // COMPLIANT
86+
func_ptr2; // COMPLIANT
87+
&func_ptr1; // COMPLIANT
88+
&func_ptr2; // COMPLIANT
89+
(func_ptr1)(); // COMPLIANT
90+
(func_ptr2)(1, "hello"); // COMPLIANT
91+
(*func_ptr1)(); // COMPLIANT
92+
(*func_ptr2)(1, "hello"); // COMPLIANT
93+
take_func(func_ptr1, func_ptr2); // COMPLIANT
94+
(void *)func_ptr1; // COMPLIANT
95+
(void *)&func_ptr1; // COMPLIANT
96+
(void *)(&func_ptr1); // COMPLIANT
97+
(void *)func_ptr1; // COMPLIANT
98+
(void *)(func_ptr1); // COMPLIANT
99+
((void *)func_ptr1); // COMPLIANT
100+
MACRO_IDENTITY(func_ptr1); // COMPLIANT
101+
MACRO_IDENTITY(func_ptr1)(); // COMPLIANT
102+
MACRO_IDENTITY(&func_ptr1); // COMPLIANT
103+
(*MACRO_IDENTITY(&func_ptr1))(); // COMPLIANT
104+
MACRO_INVOKE_RISKY(func_ptr3); // COMPLIANT
105+
MACRO_INVOKE_IMPROVED(func_ptr3); // COMPLIANT
106+
MACRO_INVOKE_IMPROVED(*&func_ptr3); // COMPLIANT
107+
}
+26Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
2+
import cpp
3+
import RuleMetadata
4+
import codingstandards.cpp.exclusions.RuleMetadata
5+
6+
newtype FunctionTypesQuery = TFunctionAddressesShouldAddressOperatorQuery()
7+
8+
predicate isFunctionTypesQueryMetadata(Query query, string queryId, string ruleId, string category) {
9+
query =
10+
// `Query` instance for the `functionAddressesShouldAddressOperator` query
11+
FunctionTypesPackage::functionAddressesShouldAddressOperatorQuery() and
12+
queryId =
13+
// `@id` for the `functionAddressesShouldAddressOperator` query
14+
"c/misra/function-addresses-should-address-operator" and
15+
ruleId = "RULE-17-12" and
16+
category = "advisory"
17+
}
18+
19+
module FunctionTypesPackage {
20+
Query functionAddressesShouldAddressOperatorQuery() {
21+
//autogenerate `Query` type
22+
result =
23+
// `Query` type for `functionAddressesShouldAddressOperator` query
24+
TQueryC(TFunctionTypesPackageQuery(TFunctionAddressesShouldAddressOperatorQuery()))
25+
}
26+
}

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

Copy file name to clipboardExpand all lines: cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import Declarations8
2929
import EssentialTypes
3030
import Expressions
3131
import FloatingTypes
32+
import FunctionTypes
3233
import IO1
3334
import IO2
3435
import IO3
@@ -102,6 +103,7 @@ newtype TCQuery =
102103
TEssentialTypesPackageQuery(EssentialTypesQuery q) or
103104
TExpressionsPackageQuery(ExpressionsQuery q) or
104105
TFloatingTypesPackageQuery(FloatingTypesQuery q) or
106+
TFunctionTypesPackageQuery(FunctionTypesQuery q) or
105107
TIO1PackageQuery(IO1Query q) or
106108
TIO2PackageQuery(IO2Query q) or
107109
TIO3PackageQuery(IO3Query q) or
@@ -175,6 +177,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
175177
isEssentialTypesQueryMetadata(query, queryId, ruleId, category) or
176178
isExpressionsQueryMetadata(query, queryId, ruleId, category) or
177179
isFloatingTypesQueryMetadata(query, queryId, ruleId, category) or
180+
isFunctionTypesQueryMetadata(query, queryId, ruleId, category) or
178181
isIO1QueryMetadata(query, queryId, ruleId, category) or
179182
isIO2QueryMetadata(query, queryId, ruleId, category) or
180183
isIO3QueryMetadata(query, queryId, ruleId, category) or

‎docs/user_manual.md

Copy file name to clipboardExpand all lines: docs/user_manual.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ The datasheet _"CodeQL Coding Standards: supported rules"_, provided with each r
7878

7979
[^1]: AUTOSAR C++ versions R22-11, R21-11, R20-11, R19-11 and R19-03 are all identical as indicated in the document change history.
8080
[^2]: The unimplemented supportable AUTOSAR rules are `A7-1-8` and `A8-2-1`. These rules require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules.
81-
[^3]: The unimplemented supportable MISRA C 2012 rules are `Rule 9.5` and `Dir 4.14`. `Rule 9.5` requires additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. `Dir 4.14` is covered by the default CodeQL queries, which identify potential security vulnerabilities caused by not validating external input.
81+
[^3]: The unimplemented supportable MISRA C 2012 rules are `Rule 9.5`, `Rule 17.13`, and `Dir 4.14`. `Rule 9.5` and `Rule 17.13` require additional support in the CodeQL CLI to ensure the required information is available in the CodeQL database to identify violations of these rules. `Dir 4.14` is covered by the default CodeQL queries, which identify potential security vulnerabilities caused by not validating external input.
8282
[^4]: The rules 5.13.7, 19.0.1 and 19.1.2 are not planned to be implemented by CodeQL as they are compiler checked in all supported compilers.
8383

8484
## Supported environment

‎rule_packages/c/FunctionTypes.json

Copy file name to clipboard
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"MISRA-C-2012": {
3+
"RULE-17-12": {
4+
"properties": {
5+
"obligation": "advisory"
6+
},
7+
"queries": [
8+
{
9+
"description": "A function identifier should only be called with a parenthesized parameter list or used with a & (address-of).",
10+
"kind": "problem",
11+
"name": "A function identifier should only be called with a parenthesized parameter list or used with a &",
12+
"precision": "very-high",
13+
"severity": "error",
14+
"short_name": "FunctionAddressesShouldAddressOperator",
15+
"tags": [
16+
"readability",
17+
"external/misra/c/2012/amendment3"
18+
]
19+
}
20+
],
21+
"title": "A function identifier should only be called with a parenthesized parameter list or used with a & (address-of)"
22+
}
23+
}
24+
}

‎rules.csv

Copy file name to clipboardExpand all lines: rules.csv
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ c,MISRA-C-2012,RULE-17-9,Yes,Mandatory,,,Verify that a function declared with _N
739739
c,MISRA-C-2012,RULE-17-10,Yes,Required,,,A function declared with _noreturn shall have a return type of void,,NoReturn,Easy,
740740
c,MISRA-C-2012,RULE-17-11,Yes,Advisory,,,A function without a branch that returns shall be declared with _Noreturn,,NoReturn,Easy,
741741
c,MISRA-C-2012,RULE-17-12,Yes,Advisory,,,A function identifier should only be called with a parenthesized parameter list or used with a & (address-of),,FunctionTypes,Easy,
742-
c,MISRA-C-2012,RULE-17-13,Yes,Required,,,"A function type shall not include any type qualifiers (const, volatile, restrict, or _Atomic)",,FunctionTypes,Easy,
742+
c,MISRA-C-2012,RULE-17-13,No,Required,,,"A function type shall not include any type qualifiers (const, volatile, restrict, or _Atomic)",,,Easy,
743743
c,MISRA-C-2012,RULE-18-1,Yes,Required,,,A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand,M5-0-16,Pointers1,Import,
744744
c,MISRA-C-2012,RULE-18-2,Yes,Required,,,Subtraction between pointers shall only be applied to pointers that address elements of the same array,M5-0-17,Pointers1,Import,
745745
c,MISRA-C-2012,RULE-18-3,Yes,Required,,,"The relational operators >, >=, < and <= shall not be applied to objects of pointer type except where they point into the same object",M5-0-18,Pointers1,Import,

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.