Skip to content

Commit 0ece5fe

Browse files
committed
Preprocessor5: add Rule MSC38-C
1 parent b68029c commit 0ece5fe

File tree

10 files changed

+125
-4
lines changed

10 files changed

+125
-4
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# MSC38-C: Do not treat a predefined identifier as an object if it might only be implemented as a macro
2+
3+
This query implements the CERT-C rule MSC38-C:
4+
5+
> Do not treat a predefined identifier as an object if it might only be implemented as a macro
6+
7+
## CERT
8+
9+
** REPLACE THIS BY RUNNING THE SCRIPT `scripts/help/cert-help-extraction.py` **
10+
11+
## Implementation notes
12+
13+
None
14+
15+
## References
16+
17+
* CERT-C: [MSC38-C: Do not treat a predefined identifier as an object if it might only be implemented as a macro](https://wiki.sei.cmu.edu/confluence/display/c)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* @id c/cert/do-not-treat-a-predefined-identifier-as-object
3+
* @name MSC38-C: Do not treat a predefined identifier as an object if it might only be implemented as a macro
4+
* @description Accessing an object or function that expands to one of a few specific standard
5+
* library macros is undefined behaviour.
6+
* @kind problem
7+
* @precision very-high
8+
* @problem.severity warning
9+
* @tags external/cert/id/msc38-c
10+
* correctness
11+
* readability
12+
* external/cert/obligation/rule
13+
*/
14+
15+
import cpp
16+
import codingstandards.c.cert
17+
18+
predicate hasRestrictedMacroName(string s) {
19+
s = "assert"
20+
or
21+
s = "errno"
22+
or
23+
s = "math_errhandling"
24+
or
25+
s = "setjmp"
26+
or
27+
s = "va_arg"
28+
or
29+
s = "va_copy"
30+
or
31+
s = "va_end"
32+
or
33+
s = "va_start"
34+
}
35+
36+
from Element m, string name, string condition
37+
where
38+
not isExcluded(m, Preprocessor5Package::doNotTreatAPredefinedIdentifierAsObjectQuery()) and
39+
(
40+
condition = "Access" and
41+
m.(Access).getTarget().hasName(name)
42+
or
43+
m.(Declaration).hasGlobalName(name) and
44+
condition = "Redefinition"
45+
) and
46+
hasRestrictedMacroName(name)
47+
select m, condition + " of standard library macro " + name + "."

c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
* @precision high
99
* @problem.severity warning
1010
* @tags external/cert/id/pre32-c
11-
* readability
1211
* correctness
12+
* readability
1313
* external/cert/obligation/rule
1414
*/
1515

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| test.c:3:12:3:16 | errno | Redefinition of standard library macro errno. |
2+
| test.c:10:21:10:26 | assert | Access of standard library macro assert. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.ql

c/cert/test/rules/MSC38-C/test.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <assert.h>
2+
3+
extern int errno; // NON_COMPLIANT
4+
5+
typedef void (*handler_type)(int);
6+
7+
void execute_handler(handler_type handler, int value) { handler(value); }
8+
9+
void f(int e) {
10+
execute_handler(&(assert), e < 0); // NON_COMPLIANT
11+
}
12+
13+
static void assert_handler(int value) { assert(value); }
14+
15+
void f2(int e) {
16+
execute_handler(&assert_handler, e < 0); // COMPLIANT
17+
}

c/common/test/includes/standard-library/assert.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <features.h>
22

33
#undef assert
4+
void assert(int i);
45

56
#ifdef NDEBUG
67
#define assert(x) (void)0

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,19 @@ import RuleMetadata
44
import codingstandards.cpp.exclusions.RuleMetadata
55

66
newtype Preprocessor5Query =
7+
TDoNotTreatAPredefinedIdentifierAsObjectQuery() or
78
TMacroOrFunctionArgsContainHashTokenQuery() or
89
TMacroParameterNotEnclosedInParenthesesCQueryQuery()
910

1011
predicate isPreprocessor5QueryMetadata(Query query, string queryId, string ruleId) {
12+
query =
13+
// `Query` instance for the `doNotTreatAPredefinedIdentifierAsObject` query
14+
Preprocessor5Package::doNotTreatAPredefinedIdentifierAsObjectQuery() and
15+
queryId =
16+
// `@id` for the `doNotTreatAPredefinedIdentifierAsObject` query
17+
"c/cert/do-not-treat-a-predefined-identifier-as-object" and
18+
ruleId = "MSC38-C"
19+
or
1120
query =
1221
// `Query` instance for the `macroOrFunctionArgsContainHashToken` query
1322
Preprocessor5Package::macroOrFunctionArgsContainHashTokenQuery() and
@@ -26,6 +35,13 @@ predicate isPreprocessor5QueryMetadata(Query query, string queryId, string ruleI
2635
}
2736

2837
module Preprocessor5Package {
38+
Query doNotTreatAPredefinedIdentifierAsObjectQuery() {
39+
//autogenerate `Query` type
40+
result =
41+
// `Query` type for `doNotTreatAPredefinedIdentifierAsObject` query
42+
TQueryC(TPreprocessor5PackageQuery(TDoNotTreatAPredefinedIdentifierAsObjectQuery()))
43+
}
44+
2945
Query macroOrFunctionArgsContainHashTokenQuery() {
3046
//autogenerate `Query` type
3147
result =

rule_packages/c/Preprocessor5.json

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
{
22
"CERT-C": {
3+
"MSC38-C": {
4+
"properties": {
5+
"obligation": "rule"
6+
},
7+
"queries": [
8+
{
9+
"description": "Accessing an object or function that expands to one of a few specific standard library macros is undefined behaviour.",
10+
"kind": "problem",
11+
"name": "Do not treat a predefined identifier as an object if it might only be implemented as a macro",
12+
"precision": "very-high",
13+
"severity": "warning",
14+
"short_name": "DoNotTreatAPredefinedIdentifierAsObject",
15+
"tags": [
16+
"correctness",
17+
"readability"
18+
]
19+
}
20+
],
21+
"title": "Do not treat a predefined identifier as an object if it might only be implemented as a macro"
22+
},
323
"PRE32-C": {
424
"properties": {
525
"obligation": "rule"
@@ -13,8 +33,8 @@
1333
"severity": "warning",
1434
"short_name": "MacroOrFunctionArgsContainHashToken",
1535
"tags": [
16-
"readability",
17-
"correctness"
36+
"correctness",
37+
"readability"
1838
]
1939
}
2040
],

rules.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ c,CERT-C,MSC30-C,Yes,Rule,,,Do not use the rand() function for generating pseudo
565565
c,CERT-C,MSC32-C,Yes,Rule,,,Properly seed pseudorandom number generators,MSC51-CPP,Misc,Easy,
566566
c,CERT-C,MSC33-C,Yes,Rule,,,Do not pass invalid data to the asctime() function,,Contracts,Easy,
567567
c,CERT-C,MSC37-C,Yes,Rule,,,Ensure that control never reaches the end of a non-void function,,Misc,Easy,
568-
c,CERT-C,MSC38-C,Yes,Rule,,,Do not treat a predefined identifier as an object if it might only be implemented as a macro,M17-0-2,Preprocessor,Medium,
568+
c,CERT-C,MSC38-C,Yes,Rule,,,Do not treat a predefined identifier as an object if it might only be implemented as a macro,M17-0-2,Preprocessor5,Medium,
569569
c,CERT-C,MSC39-C,Yes,Rule,,,Do not call va_arg() on a va_list that has an indeterminate value,,Contracts,Hard,
570570
c,CERT-C,MSC40-C,Yes,Rule,,,Do not violate constraints,,Contracts,Very Hard,
571571
c,CERT-C,MSC41-C,OutOfScope,Rule,,,Never hard code sensitive information,,,,

0 commit comments

Comments
 (0)