...
The getenv()
function is not thread-safe. Make sure to address any possible race conditions resulting from the use of this function.
...
Noncompliant Code Example
This non-compliant noncompliant code example compares the value of the TMP
and TEMP
environment variables to determine if they are the same. This code example is non-compliant noncompliant because the string referenced by tmpvar
may be overwritten as a result of the second call to the getenv()
function. As a result, it is possible that both tmpvar
and tempvar
will compare equal even if the two environment variables have different values.
Code Block | ||
---|---|---|
| ||
char *tmpvar; char *tempvar; tmpvar = getenv("TMP"); if (!tmpvar) return -1; tempvar = getenv("TEMP"); if (!tempvar) return -1; if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Error */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } |
Compliant Solution (Windows)
Wiki Markup |
---|
Windows provides the [{{getenv_s()}} and {{\_wgetenv_s()}}|http://msdn.microsoft.com/en-us/library/tb2sfw2z(VS.80).aspx] functions for getting a value from the current environment \[[MSDN|AA. C References#MSDN]\]. |
Code Block | ||
---|---|---|
| ||
char *tmpvar; char *tempvar; size_t requiredSize; getenv_s(&requiredSize, NULL, 0, "TMP"); tmpvar = (char *)malloc(requiredSize * sizeof(char)); if (!tmpvar) { /* Handle error */ } getenv_s(&requiredSize, tmpvar, requiredSize, "TMP" ); getenv_s(&requiredSize, NULL, 0, "TEMP"); tempvar = (char *)malloc(requiredSize * sizeof(char)); if (!tempvar) { free(tmpvar); tmpvar = NULL; /* Handle error */ } getenv_s(&requiredSize, tempvar, requiredSize, "TEMP" ); if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Error */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
Compliant Solution (Windows)
Wiki Markup |
---|
Windows also provides the [{{\_dupenv_s()}} and {{\_wdupenv_s()}}|http://msdn.microsoft.com/en-us/library/ms175774.aspx] functions for getting a value from the current environment \[[MSDN|AA. C References#MSDN]\]. |
...
Code Block | ||
---|---|---|
| ||
char *tmpvar; char *tempvar; size_t len; errno_t err = _dupenv_s(&tmpvar, &len, "TMP"); if (err) return -1; errno_t err = _dupenv_s(&tempvar, &len, "TEMP"); if (err) { free(tmpvar); tmpvar = NULL; return -1; } if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Error */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
Compliant Solution (POSIX)
Wiki Markup |
---|
POSIX provides the [{{strdup()}}|http://www.opengroup.org/onlinepubs/009695399/functions/strdup.html] function which can make a copy of the environment variable string \[[Open Group 04|AA. C References#Open Group 04]\]. The {{strdup()}} function is also included in ISO/IEC PDTR 24731-2 \[[ISO/IEC PDTR 24731-2|AA. C References#ISO/IEC ISO/IEC PDTR 24731-2]\]. |
Code Block | ||
---|---|---|
| ||
char *tmpvar; char *tempvar; char *temp = getenv("TMP"); if (temp != NULL) { tmpvar = strdup(temp); if (tmpvar == NULL) { /* Handle Error */ } } else { return -1; } temp = getenv("TEMP"); if (temp != NULL) { tempvar = strdup(temp); if (tempvar == NULL) { free(tmpvar); tmpvar = NULL; /* Handle Error */ } } else { free(tmpvar); tmpvar = NULL; return -1; } if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Error */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
Compliant Solution
This compliant solution uses only the C99 malloc()
and strcpy()
functions to copy the string returned by getenv()
into a dynamically allocated buffer.
Code Block | ||
---|---|---|
| ||
char *tmpvar; char *tempvar; char *temp = getenv("TMP"); if (temp != NULL) { tmpvar = (char *)malloc(strlen(temp)+1); if (tmpvar != NULL) { strcpy(tmpvar, temp); } else { /* Handle Error */ } } else { return -1; } temp = getenv("TEMP"); if (temp != NULL) { tempvar = (char *)malloc(strlen(temp)+1); if (tempvar != NULL) { strcpy(tempvar, temp); } else { free(tmpvar); tmpvar = NULL; /* Handle Error */ } } else { free(tmpvar); tmpvar = NULL; return -1; } if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Error */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
Risk Assessment
Storing the pointer to the string returned by getenv()
can result in overwritten environmental data.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ENV00-A C | low | probable | medium | P4 | L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.20.4, "Communication with the environment" \[[ISO/IEC PDTR 24731-2|AA. C References#ISO/IEC PDTR 24731-2-2007]\] \[[MSDN|AA. C References#MSDN]\] [{{\_dupenv_s()}} and {{\_wdupenv_s()}}|http://msdn.microsoft.com/en-us/library/ms175774.aspx], [{{getenv_s()}}, {{\_wgetenv_s()}}|http://msdn.microsoft.com/en-us/library/tb2sfw2z(VS.80).aspx] \[[Open Group 04|AA. C References#Open Group 04]\] Chapter 8, "Environment Variables", [{{strdup}}|http://www.opengroup.org/onlinepubs/009695399/functions/strdup.html] \[[Viega 03|AA. C References#Viega 03]\] Section 3.6, "Using Environment Variables Securely" |
...
10. Environment (ENV) 10. Environment (ENV) ENV01-A. Do not make assumptions about the size of an environment variable