The C Standard, 7.2224.4.6, paragraph 4 4 [ISO/IEC 9899:20112024], states
The
getenvfunction returns a pointer to a string associated with the matched list member. The string pointed to shall not be modified by the program but may be overwritten by a subsequent call to thegetenvfunction. If the specifiednamecannot be found, a null pointer is returned.
This paragraph gives an implementation the latitude, for example, to return a pointer to a statically allocated buffer. Consequently, do not store this pointer because the string data it points to may be overwritten by a subsequent call to the getenv() function or invalidated by modifications to the environment. This string should be referenced immediately and discarded. If later use is anticipated, the string should be copied so the copy can be safely referenced as needed.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void func(void) {
char *tmpvar;
char *tempvar;
const char *temp = getenv("TMP");
if (temp != NULL) {
tmpvar = (char *)malloc(strlen(temp)+1);
if (tmpvar != NULL) {
strcpy(tmpvar, temp);
} else {
/* Handle error */
}
} else {
/* Handle error */
}
temp = getenv("TEMP");
if (temp != NULL) {
tempvar = (char *)malloc(strlen(temp)+1);
if (tempvar != NULL) {
strcpy(tempvar, temp);
} else {
/* Handle error */
}
} else {
/* Handle error */
}
if (strcmp(tmpvar, tempvar) == 0) {
printf("TMP and TEMP are the same.\n");
} else {
printf("TMP and TEMP are NOT the same.\n");
}
free(tmpvar);
free(tempvar);
}
|
Compliant Solution (Annex K)
The C Standard, Annex K, provides the getenv_s() function for getting a value from the current environment. However, getenv_s() can still have data races with other threads of execution that modify the environment list.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#define __STDC_WANT_LIB_EXT1__ 1 #include <errno.h> #include <stdlib.h> #include <string.h> #include <stdio.h> void func(void) { char *tmpvar; char *tempvar; size_t requiredSize; errno_t err; err = getenv_s(&requiredSize, NULL, 0, "TMP"); if (err) { /* Handle error */ } tmpvar = (char *)malloc(requiredSize); if (!tmpvar) { /* Handle error */ } err = getenv_s(&requiredSize, tmpvar, requiredSize, "TMP" ); if (err) { /* Handle error */ } err = getenv_s(&requiredSize, NULL, 0, "TEMP"); if (err) { /* Handle error */ } tempvar = (char *)malloc(requiredSize); if (!tempvar) { /* Handle error */ } err = getenv_s(&requiredSize, tempvar, requiredSize, "TEMP" ); if (err) { /* Handle error */ } if (strcmp(tmpvar, tempvar) == 0) { printf("TMP and TEMP are the same.\n"); } else { printf("TMP and TEMP are NOT the same.\n"); } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; } |
Compliant Solution (Windows)
...
Storing the pointer to the string returned by getenv(), localeconv(), setlocale(), or strerror() can result in overwritten data.
Rule | Severity | Likelihood | Detectable | RepairableRemediation Cost | Priority | Level |
|---|---|---|---|---|---|---|
ENV34-C | Low | Probable | Yes | NoMedium | P4 | L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Compass/ROSE | |||||||||
| Cppcheck Premium | 24.9.0 | premium-cert-env34-c | Fully implemented | ||||||
| Helix QAC |
| DF2681, DF2682, DF2683 | |||||||
| Klocwork |
| MISRA.STDLIB.ILLEGAL_REUSE.2012_AMD1 | |||||||
| LDRA tool suite |
| 133 D | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-ENV34-a | Pointers returned by certain Standard Library functions should not be used following a subsequent call to the same or related function | ||||||
| CERT C: Rule ENV34-C | Checks for misuse of return value from nonreentrant standard function (rule fully covered) |
Related Guidelines
Key here (explains table format and definitions)
...
| [IEEE Std 1003.1:2013] | Chapter 8, "Environment Variables" XSH, System Interfaces, strdup |
| [ISO/IEC 9899:20112024] | Subclause 7.2224.4, "Communication with the Environment" Subclause 7.2224.4.6, "The getenv Function"Subclause K.3.6.2.1, "The getenv_s Function" |
| [MSDN] | _dupenv_s(), _wdupenv_s() |
| [Viega 2003] | Section 3.6, "Using Environment Variables Securely" |
...