Section 7.19.9.3 of C99 defines the following behavior for fsetpos(): [[ISO/IEC 9899:1999]]
The
fsetposfunction sets thembstate_tobject (if any) and file position indicator for the stream pointed to bystreamaccording to the value of the object pointed to bypos, which shall be a value obtained from an earlier successful call to thefgetposfunction on a stream associated with the same file.
Consequently, using any other values for pos will result in undefined behavior and should be avoided.
Non-Compliant Code Example
The following non-compliant code attempts to read three values from a file and then set the cursor position back to the beginning of the file and return to the caller.
enum { NO_FILE_POS_VALUES = 3 };
int opener(
FILE* file,
unsigned int *width,
unsigned int *height,
unsigned int *data_offset
) {
unsigned int file_w;
unsigned int file_h;
unsigned int file_o;
int rc;
fpos_t offset;
memset(&offset, 0, sizeof(offset));
if (file == NULL) { return EINVAL; }
if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o)
!= NO_FILE_POS_VALUES) { return EIO; }
rc = fsetpos(file, &offset);
if (rc != 0 ) { return rc; }
*width = file_w;
*height = file_h;
*data_offset = file_o;
return 0;
}
However, because only the return value of a fgetpos() call is a valid argument to fsetpos(); passing an fpos_t value that was created in any other way may not work. It is possible that the position will be set to an arbitrary location in the file.
Compliant Solution
In this compliant solution, the initial file position indicator is stored by first calling fgetpos(), which is used to restore the state to the beginning of the file in the later call to fsetpos().
enum { NO_FILE_POS_VALUES = 3 };
int opener(
FILE* file,
unsigned int *width,
unsigned int *height,
unsigned int *data_offset
) {
unsigned int file_w;
unsigned int file_h;
unsigned int file_o;
int rc;
fpos_t offset;
if (file == NULL) { return EINVAL; }
rc = fgetpos(file, &offset);
if (rc != 0 ) { return rc; }
if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o)
!= NO_FILE_POS_VALUES) { return EIO; }
rc = fsetpos(file, &offset);
if (rc != 0 ) { return rc; }
*width = file_w;
*height = file_h;
*data_offset = file_o;
return 0;
}
Risk Assessment
The misuse of fsetpos() can move a file stream read to a unintended location in the file. If this location held input from the user, the user would then gain control of the variables being read from the file.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
FIO44-C |
medium |
unlikely |
medium |
P4 |
L3 |
Automated Detection
Fortify SCA Version 5.0 with CERT C Rule Pack can detect violations of this rule.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899:1999]] Section 7.19.9.3, "The fsetpos function"
FIO43-C. Do not create temporary files in shared directories 09. Input Output (FIO) 10. Environment (ENV)