Calling fsetpos() sets the file position indicator of a file stream. By C99 definition, the only values that are correct for the position parameter for fsetpos() are values returned from the fgetpos(). Using any other values will result in undefined behavior and should be avoided.
Non-Compliant Code Example
The following non-compliant code attempts to read two parameters from a file, then set the cursor position back to the beginning of the file and return to the caller.
errno_t opener(FILE* file, int *width, int *height, int *data_offset) {
int file_w;
int file_h;
int file_o;
int rc;
int offset = 0;
if (file == NULL) { return EINVAL; }
if (fscanf(file, "%i %i %i", &file_w, &file_h, &file_o) != 3) { return EIO; }
rc = fsetpos(file, &offset);
if (rc != 0) { return rc; }
*width = file_w;
*height = file_h;
*data_offset = file_o;
return 0;
}
int main(void) {
int width;
int height;
int data_offset;
FILE *file;
...
file = fopen("myfile", "rb");
if(opener(file, &width, &height, &data_offset) != 0 ) { return 0; }
...
}
However, since only the return value of a getpos() call is valid to be used with setpos(), passing a specified int in instead 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 back to the beginning of the file in the later call to fsetpos().
errno_t opener(FILE* file, int *width, int *height, int *data_offset) {
int file_w;
int file_h;
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, "%i %i %i", &file_w, &file_h, &file_o) != 3) { return EIO; }
rc = fsetpos(file, &offset);
if (rc != 0) { return rc; }
*width = file_w;
*height = file_h;
*data_offset = file_o;
return 0;
}
int main(void) {
int width;
int height;
int data_offset;
FILE *file;
...
file = fopen("myfile", "rb");
if (opener(file, &width, &height, &data_offset) != 0 ) { return 0; }
...
}
Risk Assessment
The misuse of fsetpos() could move a file stream read to a undesired location in the file. If this location held input from user the user would then gain control of the variables being read from the file.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
FIO44-C |
2 (medium) |
1 (low) |
2 (medium) |
P2 |
L3 |
References
[[ISO/IEC 9899-1999:TC2]] Section 7.19.9.3, "The fsetpos function"