You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: c/cert/src/rules/MSC38-C/DoNotTreatAPredefinedIdentifierAsObject.md
+20-21Lines changed: 20 additions & 21 deletions
Original file line number
Diff line number
Diff line change
@@ -5,34 +5,33 @@ This query implements the CERT-C rule MSC38-C:
5
5
> Do not treat a predefined identifier as an object if it might only be implemented as a macro
6
6
7
7
8
-
9
8
## Description
10
9
11
10
The C Standard, 7.1.4 paragraph 1, \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO%2FIEC9899-2011)\] states
12
11
13
-
> Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.<sup>185</sup>
12
+
> Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.<sup>185</sup>
14
13
15
14
16
15
185. This means that an implementation shall provide an actual function for each library function, even if it also provides a macro for that function.
17
16
18
-
However, the C Standard enumerates specific exceptions in which the behavior of accessing an object or function expanded to be a standard library macro definition is [undefined](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior). The macros are `assert`, `errno`, `math_errhandling`, `setjmp`, `va_arg`, `va_copy`, `va_end`, and `va_start`. These cases are described by [undefined behaviors](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior) [110](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_110), [114](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_114), [122](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_122), [124](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_124), and [138](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_138). Programmers must not suppress these macros to access the underlying object or function.
17
+
However, the C Standard enumerates specific exceptions in which the behavior of accessing an object or function expanded to be a standard library macro definition is [undefined](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior). The macros are `assert`, `errno`, `math_errhandling`, `setjmp`, `va_arg`, `va_copy`, `va_end`, and `va_start`. These cases are described by [undefined behaviors](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior) [110](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_110), [114](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_114), [122](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_122), [124](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_124), and [138](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_138). Programmers must not suppress these macros to access the underlying object or function.
19
18
20
19
## Noncompliant Code Example (assert)
21
20
22
-
In this noncompliant code example, the standard`assert()` macro is suppressed in an attempt to pass it as a function pointer to the`execute_handler()` function.Attempting to suppress the `assert()` macro is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
21
+
In this noncompliant code example, the standard`assert()` macro is suppressed in an attempt to pass it as a function pointer to the`execute_handler()` function.Attempting to suppress the `assert()` macro is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior).
23
22
24
23
```cpp
25
24
#include<assert.h>
26
-
25
+
27
26
typedefvoid (*handler_type)(int);
28
-
27
+
29
28
void execute_handler(handler_type handler, int value) {
30
-
handler(value);
29
+
handler(value);
31
30
}
32
-
31
+
33
32
void func(int e) {
34
-
execute_handler(&(assert), e < 0);
35
-
}
33
+
execute_handler(&(assert), e < 0);
34
+
}
36
35
```
37
36
38
37
## Compliant Solution (assert)
@@ -41,19 +40,19 @@ In this compliant solution, the `assert()` macro is wrapped in a helper function
41
40
42
41
```cpp
43
42
#include <assert.h>
44
-
43
+
45
44
typedef void (*handler_type)(int);
46
-
45
+
47
46
void execute_handler(handler_type handler, int value) {
48
-
handler(value);
47
+
handler(value);
49
48
}
50
-
49
+
51
50
static void assert_handler(int value) {
52
-
assert(value);
51
+
assert(value);
53
52
}
54
-
53
+
55
54
void func(int e) {
56
-
execute_handler(&assert_handler, e < 0);
55
+
execute_handler(&assert_handler, e < 0);
57
56
}
58
57
```
59
58
@@ -66,15 +65,15 @@ extern int errno;
66
65
67
66
```
68
67
69
-
## Compliant Solution (Declaringerrno)
68
+
## Compliant Solution (Declaringerrno)
70
69
71
70
This compliant solution demonstrates the correct way to declare `errno` by including the header `<errno.h>`:
72
71
73
72
```cpp
74
73
#include<errno.h>
75
74
76
75
```
77
-
[C-conforming](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-conformingprogram)[implementations](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation)are required to declare `errno` in `<errno.h>`, although some historic implementations failed to do so.
76
+
[C-conforming](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-conformingprogram)[implementations](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation)are required to declare `errno` in `<errno.h>`, although some historic implementations failed to do so.
78
77
79
78
## Risk Assessment
80
79
@@ -85,7 +84,7 @@ Accessing objects or functions underlying the specific macros enumerated in this
85
84
86
85
## Automated Detection
87
86
88
-
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>BADMACRO.STDARG_H</strong> </td> <td> Use of <stdarg.h> Feature </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C3437, C3475</strong> <strong>C++3127, C++5039</strong> </td> <td> </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-MSC38-a</strong> </td> <td> A function-like macro shall not be invoked without all of its arguments </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022a </td> <td> <a> CERT C: Rule MSC38-C </a> </td> <td> Checks for predefined macro used as an object (rule fully covered) </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>3437, 3475</strong> </td> <td> </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> </tbody> </table>
87
+
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>BADMACRO.STDARG_H</strong> </td> <td> Use of <stdarg.h> Feature </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C3437, C3475</strong> <strong>C++3127, C++5039</strong> </td> <td> </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-MSC38-a</strong> </td> <td> A function-like macro shall not be invoked without all of its arguments </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022a </td> <td> <a> CERT C: Rule MSC38-C </a> </td> <td> Checks for predefined macro used as an object (rule fully covered) </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>3437, 3475</strong> </td> <td> </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> </td> <td> Supported, but no explicit checker </td> </tr> </tbody> </table>
89
88
90
89
91
90
## Related Vulnerabilities
@@ -106,7 +105,7 @@ Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+D
106
105
107
106
## Implementation notes
108
107
109
-
None
108
+
This query reports locations corresponding to both redefinitions of those standard library macros as well as locations where the identifiers used for accesses.
Copy file name to clipboardExpand all lines: c/cert/src/rules/PRE32-C/MacroOrFunctionArgsContainHashToken.md
+6-6Lines changed: 6 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ This query implements the CERT-C rule PRE32-C:
8
8
9
9
## Description
10
10
11
-
The arguments to a macro must not include preprocessor directives, such as `#define`, `#ifdef`, and `#include`. Doing so results in [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior), according to the C Standard, 6.10.3,paragraph 11 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\]:
11
+
The arguments to a macro must not include preprocessor directives, such as `#define`, `#ifdef`, and `#include`. Doing so results in [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior), according to the C Standard, 6.10.3,paragraph 11 \[[ISO/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\]:
12
12
13
13
> The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. **If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.**
14
14
@@ -23,7 +23,7 @@ In this noncompliant code example \[[GCC Bugs](http://gcc.gnu.org/bugs.html#nonb
23
23
24
24
```cpp
25
25
#include<string.h>
26
-
26
+
27
27
voidfunc(const char *src) {
28
28
/* Validate the source string; calculate size */
29
29
char *dest;
@@ -35,7 +35,7 @@ void func(const char *src) {
35
35
24
36
36
#endif
37
37
);
38
-
/* ... */
38
+
/* ... */
39
39
}
40
40
41
41
```
@@ -50,7 +50,7 @@ In this compliant solution \[[GCC Bugs](http://gcc.gnu.org/bugs.html#nonbugs_c)\
50
50
void func(const char *src) {
51
51
/* Validate the source string; calculate size */
52
52
char *dest;
53
-
/* malloc() destination string */
53
+
/* malloc() destination string */
54
54
#ifdef PLATFORM1
55
55
memcpy(dest, src, 12);
56
56
#else
@@ -69,7 +69,7 @@ Including preprocessor directives in macro arguments is undefined behavior.
0 commit comments