Many functions require the allocation of multiple resources. Failing and returning somewhere in the middle of this function without freeing all of the allocated resources could produce a memory leak. It is a common error to forget to free one (or all) of the resources in this manner, so a goto
chain is the simplest and cleanest way to organize exits while preserving the order of freed resources.
Noncompliant Code Example
In this noncompliant example, exit code is written for every instance in which the function can terminate prematurely. Notice how failing to close fin2
produces a resource leak, leaving an open file descriptor.
Please note that these examples assume errno_t
and NOERR
to be defined, as recommended in DCL09-C. Declare functions that return errno with a return type of errno_t. An equivalent compatible example would define errno_t
as an int
and NOERR
as zero.
This is just a small example; in much larger examples, errors like this are even harder to detect.
Compliant Solution
In this revised version, a goto
chain replaces each individual return segment. If no error occurs, control flow falls through to the SUCCESS
label, releases all of the resources, and returns NOERR
. If an error occurs, the return value is set to errno
, control flow jumps to the proper failure label, and the appropriate resources are released before returning.
This method is beneficial because the code is cleaner, and the programmer does not need to rewrite similar code upon every function error.
Compliant Solution (copy_process()
from Linux kernel)
Some effective examples of goto
chains are quite large. This compliant solution is an excerpt from the Linux kernel. This is the copy_process
function from kernel/fork.c
from version 2.6.29 of the kernel.
The function uses 17 goto
labels (not all displayed here) to perform cleanup code should any internal function yield an error code. If no errors occur, the program returns a pointer to the new process p
. If any error occurs, the program diverts control to a particular goto
label, which performs cleanup for sections of the function that have currently been successfully executed but not for sections that have not yet been executed. Consequently, only resources that were successfully opened are actually closed.
All comments in this excerpt were added to indicate additional code in the kernel not displayed here.
Risk Assessment
Failure to free allocated memory or close opened files results in a memory leak and possibly unexpected results.
Recommendation | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MEM12-C | Low | Probable | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
CERT C Rules implemented in the LDRA tool suite | 9.7.1 | 50 D | Partially Implemented |
Bibliography
Linux Kernel Sourcecode (v2.6.xx) | 2.6.29, kernel/fork.c , the copy_process() Function |
[AA. Bibliography#Seacord 2013] | Chapter 4, "Dynamic Memory Management" |