...
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 (
...
C11 Annex K)
Windows C11 Annex K provides the getenv_s()
and _wgetenv_s()
functions function for getting a value from the current environment [MSDN]:ISO/IEC 9899:2011]. However, note that according to the standard, getenv_s()
can still have data races with other threads of execution which modify the environment list.
Code Block | ||||
---|---|---|---|---|
| ||||
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 * sizeof(char)); 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 * sizeof(char)); if (!tempvar) { free(tmpvar); tmpvar = NULL; /* Handle error */ } err = getenv_s(&requiredSize, tempvar, requiredSize, "TEMP" ); if (err) { /* Handle error */ } if (strcmp(tmpvar, tempvar) == 0) { if printf(puts("TMP and TEMP are the same.\n") == EOF) { /* Handle error */ } } ; } else { if printf(puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle Error */ } } ; } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
Compliant Solution (Windows)
Windows also provides the _dupenv_s()
and wdupenv_s()
functions for getting a value from the current environment [MSDN]. The _dupenv_s()
function searches the list of environment variables for a specified name. If the name is found, a buffer is allocated; the variable's value is copied into the buffer, and the buffer's address and number of elements are returned. By allocating the buffer itself, _dupenv_s()
and _wdupenv_s()
provide a more convenient alternative to getenv_s()
and _wgetenv_s()
.
...
Code Block | ||||
---|---|---|---|---|
| ||||
char *tmpvar; char *tempvar; size_t len; errno_t err = _dupenv_s(&tmpvar, &len, "TMP"); if (err) { return -1;/* Handle error */ } err = _dupenv_s(&tempvar, &len, "TEMP"); if (err) { free(tmpvar); tmpvar = NULL; return -1;/* Handle error */ } if (strcmp(tmpvar, tempvar) == 0) { if printf(puts("TMP and TEMP are the same.\n") == EOF) { /* Handle error */ } } ; } else { if printf(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; const char *temp = getenv("TMP"); if (temp != NULL) { tmpvar = strdup(temp); if (tmpvar == NULL) { /* Handle error */ } } else { return -1;/* Handle error */ } 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; /* Handle error */ } if (strcmp(tmpvar, tempvar) == 0) { if printf(puts("TMP and TEMP are the same.\n") == EOF) { /* Handle error */ } } ; } else { if printf(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; 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 return -1;error */ } 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; /* Handle error */ } if (strcmp(tmpvar, tempvar) == 0) { if printf(puts("TMP and TEMP are the same.\n") == EOF) { /* Handle error */ } } ; } else { if printf(puts("TMP and TEMP are NOT the same.\n") == EOF) { /* Handle error */ }; } free(tmpvar); tmpvar = NULL; free(tempvar); tempvar = NULL; |
...
[ISO/IEC 9899:2011] | Section 7.22.4, "Communication with the Environment" Section 7.22.4.6, "The getenv Function" |
[MSDN] | _dupenv_s() and _wdupenv_s() getenv_s() , _wgetenv_s() |
[Open Group 2004] | Chapter 8, "Environment Variables"strdup |
[Viega 2003] | Section 3.6, "Using Environment Variables Securely" |
[ISO/IEC 9899:2011] | Section K.3.6.2.1, "The getenv_s function" |
...