Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Some functions return a pointer to an object that cannot be modified without causing undefined behavior. These functions include the standard getenv(), setlocale(), localeconv(), and strerror() functions.

Section Subclause 7.22.4.6 of the C Standard [ISO/IEC 9899:2011] defines getenv as follows:

...

Consequently, if the string returned by getenv() must be altered, a local copy should be created. Altering the string returned by getenv() results in undefined behavior. See also undefined behavior 184 of Annex J of the C Standard.

Similarly, Section subclause 7.11.1.1 [ISO/IEC 9899:2011] defines setlocale and localeconv as follows:

...

Altering the string returned by setlocale() or the structure returned by localeconv() results in undefined behavior. See also undefined behaviors 120 and 121 of Annex J. Furthermore, the C Standard imposes no requirements on the contents of the string by setlocale(). Consequently, a program should make no assumptions as to the string's internal contents or structure.

Finally, Section subclause 7.24.6.2 [ISO/IEC 9899:2011], states:

...

Code Block
bgColor#ffcccc
langc
#include <stdlib.h>
 
void trstr(char *str, char orig, char rep) {
  while (*str != '\0') {
    if (*str == orig) {
      *str = rep;
    }
    str++;
  }
}

/* ... */

void func(void) {
  char *env = getenv("TEST_ENV");
  if (env == NULL) {
    /* Handle error */
  }

  trstr(env,'"', '_');


/* ... */}

Compliant Solution (getenv()) (Local Copy)

...

Code Block
bgColor#ccccFF
langc
#include <stdlib.h>
#include <string.h>
 
void trstr(char *str, char orig, char rep) {
  while (*str != '\0') {
    if (*str == orig) {
      *str = rep;
    }
    str++;
  }
}
 
void func(void) {
  const char *env;
  char *copy_of_env;

  env = getenv("TEST_ENV");
  if (env == NULL) {
    /* Handle error */
  }

  copy_of_env = (char *)malloc(strlen(env) + 1);
  if (copy_of_env == NULL) {
    /* Handle error */
  }

  strcpy(copy_of_env, env);
  trstr(copy_of_env,'\"', '_');
}

Compliant Solution (getenv()) (Modifying the Environment in POSIX)

...

Code Block
bgColor#ccccFF
langc
#include <stdlib.h>
#include <string.h>
 
void trstr(char *str, char orig, char rep) {
  while (*str != '\0') {
    if (*str == orig) {
      *str = rep;
    }
    str++;
  }
}
 
void func(void) {
  const char *env;
  char *copy_of_env;

  env = getenv("TEST_ENV");
  if (env == NULL) {
    /* Handle error */
  }

  copy_of_env = strdup(env);
  if (copy_of_env == NULL) {
    /* Handle error */
  }

  trstr(copy_of_env,'\"', '_');

  if (setenv("TEST_ENV", copy_of_env, 1) != 0) {
    /* Handle error */
  }
}

Noncompliant Code Example (localeconv())

...

Code Block
bgColor#ffcccc
langc
#include <locale.h>
 
void f2(void) {
  struct lconv *conv = localeconv();
 
  if ('\0' == conv->decimal_point[0]) {
    conv->decimal_point = ".";  /* violation */
  }
 
  if ('\0' == conv->thousands_sep[0]) {
    conv->thousands_sep = ",";  /* violation */
  }
 
  /* ... */
}

Compliant Solution (localeconv()) (Local Copy)

...

Code Block
bgColor#ccccFF
langc
#include <locale.h>
#include <stdlib.h>
#include <string.h>
 
void f2(void) {
  struct lconv *conv = localeconv();
  struct lconv *copy_of_conv;
  if (conv == NULL) {
     /* Handle error */
  }
  
  copy_of_conv = (charstruct lconv*)malloc(sizeof(struct lconv) + 1);
  if (copy_of_conv == NULL) {
    /* Handle error */
  }
 
  memcpy(copy_of_conv, conv, sizeof(struct lconv));
 
  if ('\0' == copy_of_conv->decimal_point[0]) {
    copy_of_conv->decimal_point = ".";  
  }
 
  if ('\0' == copy_of_conv->thousands_sep[0]) {
    copy_of_conv->thousands_sep = ","; 
  }
 
  /* ... */
}

Risk Assessment

Depending on the implementation, modifying the object pointed to by the return value of these functions causes undefined behavior. Even if the modification succeeds, the modified object can be overwritten by a subsequent call to the getenv(), setlocale(), localeconv(), or strerror() functions.

...

Bibliography

[ISO/IEC 9899:2011]Section 7Subclause 7.11.1.1, "€œThe setlocale Function"
Section 7Subclause 7.22.4.6, "The getenv Function"
Section 7Subclause 7.24.6.2, "The strerror Function"
[Open Group 2004]getenv
setlocale
localeconv

 

...