The rename() function has the following prototype.
int rename(const char *old, const char *new);
If the file referenced by new exists prior to calling rename(), the behavior is implementation-defined. For portability, you must ensure that the file referenced by new does not exist when rename() is invoked.
Non-Compliant Code Example
In this non-compliant code example, a file is moved using rename().
/* program code */
const char *old = "oldfile.ext";
const char *new = "newfile.ext";
if (rename(old, new) != 0) {
/* Handle rename failure */
}
/* program code */
If newfile.ext exists at the time of the call to rename(), the result is implementation-defined.
Compliant Solution
This compliant solution checks for the existence of the new file before callling rename(). This code contains an unavoidable race condition between the call to fopen() and the call to rename(). Consequently, this code can only be safely executed within a secure directory.
/* program code */
const char *old = "oldfile.ext";
const char *new = "newfile.ext";
FILE *file = fopen(new, "r");
if (!file) {
if (rename(old, new) != 0) {
/* Handle rename failure */
}
} else {
fclose(file);
/* handle error condition */
}
/* program code */
Risk Assessment
Calling rename() has implementation-defined behavior when the new file name refers to an existing file. Incorrect use of rename() could result in a file being unexpectedly overwritten or other unexpected behavior.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
FIO10-A |
2 (medium) |
2 (probable) |
2 (medium) |
P8 |
L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899-1999]] Section 7.9.4.2, "The rename function"
VOID FIO09-A. fflush() should be called after writing to an output stream if data integrity is important 09. Input Output (FIO) FIO11-A. Take care when specifying the mode parameter of fopen()