Versions Compared

Key

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

Under many hosted environments it is possible to access the environment through a modified form of main():

Code Block
main(int argc, char **argv, char **envp)

...

In a hosted environment, the main function receives a third argument, char *envp[], that points to a null-terminated array of pointers to char, each of which points to a string that provides information about the environment for this execution of the program.

However, modifying the environment by using the setenv() or putenv() functions might cause , or by any other means, may cause the environment memory to be reallocated, leaving envp pointing to the wrong location. To illustratewith the reuslt that envp now references an incorrect location. For example, when compiled with gcc version n.n and run on Linux version n.n, the following code:

Code Block
extern char **environ;

int main(int argc, char **argv, char **envp) { 
   printf("environ:  %p\n", environ); 
   printf("envp:     %p\n", envp); 
   putenv("MY_NEW_VAR=new_value", 1);
   printfputs("--Added MY_NEW_VAR--\n");
   printf("environ:  %p\n", environ); 
   printf("envp:     %p\n", envp); 
}

...

Code Block
% ./envp-environ
environ: 0xbf8656ec
envp:    0xbf8656ec
--Added MY_NEW_VAR--
environ: 0x804a008
envp:    0xbf8656ec

If you need to directly access or manipulate the environment, it is safer to use environIt is evident from these results that the environment has been relocated as a result of the call to {{putenv())).

Non-Compliant

...

Code Example

After a call to setenv() or other function that modifies the environment, the envp pointer may not have no longer reference the proper environment values.

Code Block
bgColor#ffcccc
int main(int argc, char **argv[], char **envp[]) {
   setenv("MY_NEW_VAR", "new_value", 1);

   if (envp != NULL) {
      for (size_t i = 0; envp[i] != NULL; i++) {
         printf("%s\n", puts(envp[i]); 
      }
   }

   return 0;
}

Because envp no longer points to the current environment, so MY_NEW_VAR will not be found in envpthis program has undefined behavior.

Compliant Solution (POSIX)

Use environ in place of envp when defined.

Code Block
bgColor#ccccff
extern char **environ;

int main(int argc, char **argv[]) {
   setenv("MY_NEW_VAR", "new_value", 1);

   if (environ != NULL) { 
      for (size_t i = 0; environ[i] != NULL; i++) {
         printf("%s\n", puts(environ[i]); 
      }
   }

   return 0;
}

Note: if you have a great deal of unsafe envp code, you could save time in your remediation by aliasing. Change:

Code Block
main(int argc, char **argv[], char **envp[])

To:

Code Block
extern char **environ;
#define envp environ
 
main(int argc, char **argv[])

Risk Assessment

The program would not be using current environment values, causing unexpected resultsUsing the envp environment pointer after the environment has been modified may result in undefined behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ENV31-C

1 (low)

1 (low)

3 (low)

P3

L3

...