C99 [ISO/IEC 9899:1999], Section 6.5.2.2 says
If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined.
(See also undefined behavior 35 of Annex J.)
C functions may not return arrays; however, they may return structs or unions that contain arrays.
Consequently, if a function call's return value contains an array, that array should never be accessed or modified within the expression containing the function call.
The following noncompliant code attempts to retrieve an array from a struct that is returned by a function call.
#include <stdio.h>
struct X { char a[6]; };
struct X addressee(void) {
struct X result = { "world" };
return result;
}
int main(void) {
printf("Hello, %s!\n", addressee().a);
return 0;
}
|
This solution is problematic because of three inherent properties of C:
printf() is called, the struct returned by the addressee() call is no longer considered valid and could have been overwritten."Hello, %s!\n". Under most circumstances, these copies protect you from the effects of sequence points described earlier.addresee().a array, and that pointer copy is passed to printf(). But the array data itself is not copied and could no longer exist when printf() is called.Consequently, when printf() tries to dereference the pointer passed as its second argument, it is likely to find garbage.
This code compiles cleanly and runs without error under Microsoft Visual C++ Version 8.0. On GCC Compiler Version 4.2, the program compiles with a warning when the -Wall switch is used, and execution on Linux results in a segmentation fault. However, if one passes the flag --std=c99 to GCC, the program compiles with no warning and runs with no error.
This compliant solution stores the structure returned by the call to addressee() as my_x before calling the printf() function.
#include <stdio.h>
struct X { char a[6]; };
struct X addressee(void) {
struct X result = { "world" };
return result;
}
int main(void) {
struct X my_x = addressee();
printf("Hello, %s!\n", my_x.a);
return 0;
}
|
Attempting to access or modify an array within a function after a subsequent sequence point may result in unexpected and perhaps unintended program behavior.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
EXP35-C |
low |
probable |
medium |
P4 |
L3 |
Tool |
Version |
Checker |
Description |
||
|---|---|---|---|---|---|
|
|
|
|||
|
|
|
|
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
ISO/IEC 9899:1999 Section 6.5.2.2, "Function calls"
ISO/IEC TR 24772 "DCM Dangling references to stack frames" and "SAM Side-effects and order of evaluation"
03. Expressions (EXP) EXP36-C. Do not convert pointers into more strictly aligned pointer types