...
| Code Block | ||||
|---|---|---|---|---|
| ||||
int func(const char *var) {
static 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);
}
|
According to the [Open Group 2004] entry for putenv():
...the string pointed to by string shall become part of the environment, so altering the string shall change the environment.
This means that the call to putenv() is only necessary the first time func() is called, since subsequent changes to the string update the environment. If func() were called more than once, an additional variable could be added to avoid calling it unnecessarily.
Compliant Solution (Heap Memory)
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
int func(const char *var) {
static char *oldenv;
const char *env_format = "TEST=%s";
const size_t len = strlen(var) + strlen(env_format);
char *env = (char *) malloc(len);
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;
}
if (oldenv != NULL) {
free(oldenv); /* avoid memory leak */
}
oldenv = env;
return 0;
}
|
The POSIX setenv() function is preferred over this function [Open Group 2004]. In particular, using putenv() will necessarily leak memory if called multiple times for the same environment variable, due to restrictions on when you can safely free the old value. According to the [Open Group 2004] entry for putenv():
Although the space used by string is no longer used once a new string which defines name is passed to putenv(), if any thread in the application has used getenv() to retrieve a pointer to this variable, it should not be freed by calling free(). If the changed environment variable is one known by the system (such as the locale environment variables) the application should never free the buffer used by earlier calls to putenv() for the same variable.
Compliant Solution (setenv())
...
Providing a pointer to a buffer of automatic storage duration as an argument to putenv() may cause that buffer to take on an unintended value. Depending on how and when the buffer is used, it can cause unexpected program behavior or possibly allow an attacker to run arbitrary code.
Rule | Severity | Likelihood | Detectable | RepairableRemediation Cost | Priority | Level |
|---|---|---|---|---|---|---|
POS34-C | High | Unlikelyhigh | unlikelyYes | mediumNo | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| putenv-arg-local | Partially checked + soundly supported | |||||||||||
| Axivion Bauhaus Suite |
| CertC-POS34 | ||||||||||||
| CodeSonar |
| (customization) BADFUNC.PUTENV | Users can add a custom check for all uses of putenv().Use of putenv | |||||||||||
| Compass/ROSE | ||||||||||||||
| Helix QAC |
| C5024 | ||||||||||||
| Klocwork |
| CERT.PUTENV.AUTO_VARIABLE | ||||||||||||
| Parasoft C/C++test |
| CERT_C-POS34-a | Usage of system properties (environment variables) should be restricted | |||||||||||
| PC-lint Plus |
| 2601 | Fully supported | |||||||||||
| Use CERT C: Rule POS34-C | Checks for use of automatic variable as putenv-family function argument | putenv-family function argument not accessible outside its scope | PRQA QA-C(rule fully covered) | ||||||||||
| RuleChecker |
| PRQA QA-C_v |
| putenv-arg-local | Partially checked | PRQA QA-C_v | 5024 | Partially implemented
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
| [Dowd 2006] | Chapter 10, "UNIX Processes" |
| [ISO/IEC 9899:20112024] | Section 6.2.4, "Storage Durations of Objects" Section 7.2224.3, "Memory Management Functions" |
| [Open Group 2004] | putenv()setenv() |
...