Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Changed a Windows CS to a C11 CS; updated code samples

...

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
bgColor#ccccff
langc
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
bgColor#ccccff
langc
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
bgColor#ccccff
langc
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
bgColor#ccccff
langc
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"

 

...