...
The getenv function 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 the getenv function.
Consequently, it is best not to store this pointer, as it may be overwritten by a subsequent call to the getenv()
function or invalidated as a result of changes made to the environment list through calls to putenv()
, setenv()
, or other means. Storing the pointer for later use can result in a dangling pointer or a pointer to incorrect data. This string should be referenced immediately and discarded, or ; if later use is anticipated, the string should be copied so that the copy may can be referenced safely at a later timesafetly referenced as needed.
The getenv()
function is not thread-safe. Make sure to address any possible race conditions resulting from the use of this function.
...
This noncompliant code example compares the value of the TMP
and TEMP
environment variables to determine if they are the same. This code example is 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 | ||
---|---|---|
| ||
constchar *tmpvar; char *tempvar; tmpvar = getenv("TMP"); if (!tmpvar) return -1; const char *tempvar = getenv("TEMP"); if (!tempvar) return -1; if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Errorerror */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Errorerror */ } } |
This code example is 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.
Compliant Solution (Windows)
...
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 Errorerror */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
...
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 Errorerror */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Errorerror */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
...
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; const char *temp = getenv("TMP"); if (temp != NULL) { tmpvar = strdup(temp); if (tmpvar == NULL) { /* Handle Errorerror */ } } else { return -1; } temp = getenv("TEMP"); if (temp != NULL) { tempvar = strdup(temp); if (tempvar == NULL) { free(tmpvar); tmpvar = NULL; /* Handle Errorerror */ } } else { free(tmpvar); tmpvar = NULL; return -1; } if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Errorerror */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Errorerror */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
...
Code Block | ||
---|---|---|
| ||
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 Errorerror */ } } 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 Errorerror */ } } else { free(tmpvar); tmpvar = NULL; return -1; } if (strcmp(tmpvar, tempvar) == 0) { if (puts("TMP and TEMP are the same.\n") == EOF) { /* Handle Errorerror */ } } else { if (puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Errorerror */ } } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
...
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, and "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" |
...