An object has a storage duration that determines its lifetime. There are three storage durations: static, automatic, and allocated.
According to [[ISO/IEC 9899-1999]]:
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address, and retains its last-stored value throughout its lifetime. If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when
the object it points to reaches the end of its lifetime.
Referencing an object outside of its lifetime could result in exploitable vulnerabilities.
Non-Compliant Code Example 1
This non-compliant code example declares the variable p
as a pointer to a constant char
with file scope. The value of str
is assigned to p
within the dont_do_this()
function. However, str
has automatic storage duration so the lifetime of str
ends when the dont_do_this()
function exits.
char const *p; void dont_do_this() { char const str[] = "This will change"; p = str; /* dangerous */ /* ... */ } void innocuous() { char const str[] = "Surprise, surprise"; } /* ... */ dont_do_this(); innocuous(); /* now, it is likely that p is pointing to "Surprise, surprise" */
As a result of this undefined behavior, it is likely that p
will refer to the string literal "Surprise, surprise"
after the call to the innocuous()
function.
Compliant Solution 1
In this compliant solution, the pointer to the constant char p
is moved within the this_is_OK()
to prevent this variable from being accessed outside of the function.
void this_is_OK() { char const str[] = "Everything OK"; char const *p = str; /* ... */ } /* pointer p is now inaccessible outside the scope of string str */
Non-Compliant Code Example 2
In this example, the function func()
incorrectly returns a pointer to a local stack variable.
char *func() { char a[10] ; /* Operate on a */ return &a[0]; }
Compiling with appropriate warning levels should generate a warning when a local stack variable is returned from a function.
Compliant Solution 2
Correcting this example depends on the intent of the programmer. If the intent is to modify the value of a
and have that modification persist outside of the scope of func()
, then the desired behavior can be achieved by declaring a
elsewhere and passing it as a parameter to func()
.
void func(char a[]) { /* Operate on a */ return; }
Risk Assessment
Referencing an object outside of its lifetime could result in an attacker being able to run arbitrary code.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
DCL30-C |
3 (high) |
2 (probable) |
1 (high) |
P6 |
L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Automated Detection
The Coverity Prevent RETURN_LOCAL checker finds many instances where a function will return a pointer to a local stack variable.
References
[[ISO/IEC 9899-1999]] Section 6.2.4, "Storage durations of objects," and Section 7.20.3, "Memory management functions"