Wiki Markup |
---|
Local, automatic variables can assume unexpected values if they are used before they are initialized. C99 specifies, "If an object that has automatic storage duration is not initialized explicitly, its value is [indeterminate| BB. Definitions#indeterminate value]" \[[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\]. (seeSee also [undefined behavior 10 | CC. Undefined Behavior#ub_10] of Annex J.). In the common case, on [implementations| BB. Definitions#implementation] that make use of a program stack, this value defaults to whichever values are currently stored in stack memory. While uninitialized memory often contains zeroes, this is not guaranteed. On implementations that include [trap representations|BB. Definitions#trap representation], reading an uninitialized object of any type other than {{unsigned char}} (i.e., including {{int}}) may trigger a trap. (seeSee [undefined behavior 11 | CC. Undefined Behavior#ub_11] of Annex J.). Consequently, uninitialized memory can cause a program to behave in an unpredictable or unplanned manner, lead to [undefined behavior | BB. Definitions#undefined behavior], and may provide an avenue for attack. |
Additionally, memory allocated by functions, such as malloc()
, should not be used before being initialized as its contents are indeterminate.
In most cases, compilers warn about uninitialized variables. These warnings should be resolved as recommended by guidline MSC00-C. Compile cleanly at high warning levels.
...
This defect results from a failure to consider all possible data states. (see See guideline MSC01-C. Strive for logical completeness.) . Once the problem is identified, it can be trivially repaired by accounting for the possibility that number
can be equal to 0.
...
Wiki Markup |
---|
In this noncompliant code example, the programmer mistakenly fails to set the local variable {{error_log}} to the {{msg}} argument in the {{report_error()}} function \[[mercyMercy 062006|AA. Bibliography#mercy 06]\]. Because {{error_log}} has not been initialized, on architectures making use of a program stack, it assumes the value already on the stack at this location, which is a pointer to the stack memory allocated to the {{password}} array. The {{sprintf()}} call copies data in {{password}} until a null byte is reached. If the length of the string stored in the {{password}} array is greater than the size of the {{buffer}} array, then a buffer overflow occurs. |
...
This solution is still problematic in that because a buffer overflow will occur if the null-terminated byte string referenced by msg
is greater than 17 bytes, including the NULL terminator. The solution also makes use of a "magic number," which should be avoided. (see See guideline DCL06-C. Use meaningful symbolic constants to represent literal values in program logic.).
Compliant Solution
In this solution, the magic number is abstracted, and the buffer overflow is eliminated.
...
In the noncompliant code example below, the function mbrlen()
is passed the address of an automatic mbstate_t
object that has not been properly initialized, leading to undefined behavior. See undefined behavior 188 in section Section J.2 of C99.
Code Block | ||
---|---|---|
| ||
void f(const char *mbs) { size_t len; mbstate_t state; len = mbrlen(mbs, strlen(mbs), &state); /* ... */ } |
...
Before being passed to a multibyte conversion function, an mbstate_t
object must be either initialized to the initial conversion state or set to a value that corresponds to the most recent shift state by a prior call to a multibyte conversion function. The compliant solution below sets the mbstate_t
object to the initial conversion state by setting it to all zeros.
...
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP33-C | high | probable | medium | P12 | L1 |
Automated Detection
The LDRA tool suite Version 7.6.0 can detect violations of this rule.
...
Tool | Version | Checker | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
| ||||||||
|
|
|
| ||||||||
|
|
Splint Version 3.1.1 can detect violations of this rule.
...
|
|
| |||||||||||
|
|
|
| ||||||||||
|
|
|
| ||||||||||
|
...
|
|
| ||||||||||||
|
|
...
|
|
...
|
...
|
...
|
...
|
...
|
...
|
Related Vulnerabilities
CVE-2009-1888 results from a violation of this recommendation. Some versions of SAMBA (up to 3.3.5) call a function which takes in two potentially unitiliazed variables involving access rights. An attacker can exploit this to bypass the access control list and gain access to protected files [xorl 2009].
Searchfor vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
Related Guidelines
This rule appears in the C++ Secure Coding Standard as : EXP33-CPP. Do not reference uninitialized memory.
Bibliography
Wiki Markup |
---|
\[[Flake 062006|AA. Bibliography#Flake 06]\] \[[ISO/IEC 9899:1999|AA. Bibliography#ISO/IEC 9899-1999]\] Section 6.7.8, "Initialization" \[[ISO/IEC PDTR 24772|AA. Bibliography#ISO/IEC PDTR 24772]\] "LAV Initialization of Variables" \[[mercyMercy 062006|AA. Bibliography#mercy 06]\] \[[xorl 2009|AA. Bibliography#xorl 2009]\] ["CVE-2009-1888: SAMBA ACLs Uninitialized Memory Read"|http://xorl.wordpress.com/2009/06/26/cve-2009-1888-samba-acls-uninitialized-memory-read/] |
...