CERT.PUTENV.AUTO_VARIABLE

Do not call putenv() with a pointer to an automatic variable as the argument

In C / C++, the POSIX putenv() function uses the string argument to set environment variable values. The putenv() function inserts a pointer to the string into the environment array and does not create a copy of the string supplied to it as an argument. If a pointer to a buffer of automatic storage duration is supplied as an argument to putenv(), the memory allocated for that buffer may be overwritten when the containing function returns and stack memory is recycled. The CERT.PUTENV.AUTO_VARIABLE checker flags calls to putenv() that use a pointer to an automatic variable as the argument.

Vulnerability and risk

If the putenv() accesses the automatic variables, then the Environment variables can take on unintended values and may possibly leak data.

Vulnerable code example 1

Copy
   int func(const char *var) {
     char env[1024];
     int retval = snprintf(env, sizeof(env),"TEST=%s", var);
     if (retval < 0 || (size_t)retval >= sizeof(env)) {
     /* Handle error */
     }
      
     return putenv(env);                  // CERT.PUTENV.AUTO_VARIABLE
  }

In this noncompliant example, a pointer to a buffer ‘env’ of automatic storage duration is used as an argument to putenv(). If this code is executed, the TEST environment variable may take on an unintended value if it is accessed after func() has returned and the stack frame containing ‘env’ has been recycled.

Fixed code example 1

Copy
  int func(const char *var) {
     static char env[1024];               // Fixed here
  
     int retval = snprintf(env, sizeof(env),"TEST=%s", var);
     if (retval < 0 || (size_t)retval >= sizeof(env)) {
     /* Handle error */
     }
  
     return putenv(env);
 }

The problem can befixed by using static variables. For instance, in the above fixed example, the variable ‘env’ is a static variable. If this code is executed, when func() exits, putenv() will still point to a valid memory, and the environment variable ‘TEST’ will have the correct value.

Fixed code example 2

Copy
   int func(const char *var) {
      const char *env_format = "TEST=%s";
      const size_t len = strlen(var) + strlen(env_format);
      char *env = (char *) malloc(len);               // Fixed here
      if (env == NULL) {
 ...     return -1;
 ...   }
      int retval = snprintf(env, len, env_format, var);
      if (retval < 0 || (size_t)retval >= len) {
     /* Handle error */
     }
     if (putenv(env) != 0) {
     free(env);
     return -1;
     }
     return 0;
  }

This fixed example uses Heap allocated memory instead of automatic variables.