...
The following tables list these macros and indicate in which version of the C Standard they were introduced. The following macros are required:
Macro Name | C90 | C99 | C11 |
---|---|---|---|
| ✓ | ✓ | ✓ |
|
✓ | ✓ | |
|
✓ | ✓ | ||
| ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ |
| ✓ | ✓ | ✓ |
1) __STDC_VERSION__ was introduced by an Amendment to C90, this version of the C Standard is commonly call C94
The following are optional environment macros:
Macro Name | C90 | C99 | C11 |
---|---|---|---|
|
✓ | ✓ | ||
|
✓ | ✓ | ||
|
✓ | ||
|
✓ |
The following are optional feature macros:
Macro Name | C90 | C99 | C11 |
---|---|---|---|
|
✓ | |||
|
✓ | ✓ | ||
|
✓ | ✓ | |
|
|
✓ | ||
|
✓ | |||
|
✓ | |||
|
✓ | ||
|
|
✓ |
The following is optional and is defined by the user:
Macro Name | C90 | C99 | C11 |
---|---|---|---|
__STDC_WANT_LIB_EXT1__ |
✓ |
Noncompliant Code Example (Checking Value of Predefined Macro)
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h> int main(void) { #if defined(__STDC__) #if (__STDC__ == 1) printf("Implementation is ISO-conforming.\n"); #else printf("Implementation is not ISO-conforming.\n"); #endif #else /* !defined(__STDC__) */ printf("__STDC__ is not defined.\n"); #endif /* ... */ return 0; } |
Compliant Solution (Test for Optional
...
Feature)
This compliant solution tests to see if the C11 predefined macro __STDC_ANALYZABLE__
is defined and what value the implementation has given the macro:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#if defined(__STDC_LIB_EXT1__) #if (__STDC_LIB_EXT1__ >= 201112L) #define USE_EXT1 1 #define __STDC_WANT_LIB_EXT1__ 1 /* Want the ext1 functions */ #endif #endif #include <string.h> #include <stdlib.h> int main(void) { char source_msg[] = "This is a test."; char *msg = malloc(sizeof(source_msg) + 1); if (msg != NULL) { #if defined(USE_EXT1) strcpy_s(msg, sizeof msg, source_msg); #else strcpy(msg, source_msg); #endif } else { return EXIT_FAILURE; } return 0; } |
Compliant Solution (Optional Language Features)
Code Block | ||||
---|---|---|---|---|
| ||||
#if defined(__STDC_LIB_EXT1__)
#if (__STDC_LIB_EXT1__ >= 201112L)
#define USE_EXT1 1
#define __STDC_WANT_LIB_EXT1__ 1 /* Want the ext1 functions */
#endif
#endif
#include <string.h>
#include <stdlib.h>
#if !defined(USE_EXT1)
#include "safe_str_lib.h"
#endif
int main(void) {
char source_msg[] = "This is a test.";
char *msg = malloc(sizeof(source_msg) + 1);
if (msg != NULL) {
strcpy_s(msg, sizeof msg, source_msg);
}
else {
return EXIT_FAILURE;
}
return 0;
}
|
Risk Assessment
Not testing for language features or the version of the implementation being used can lead to unexpected or undefined program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
PRE13-C | Low | Probable | Low | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Axivion Bauhaus Suite |
| CertC-PRE13 | |||||||
LDRA tool suite |
| Partially implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
ISO/IEC TR 24772:2013 | Pre-processor Directives [NMP] |
ISO/IEC 9899:2011 |
6.10.8, "Predefined macro names" K.3.7.1, "Copying functions" |
...
...