The C Standard, 7.23.9.3 paragraph 2 [ISO/IEC 9899:2024], defines the following behavior for fsetpos():
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.
Invoking the fsetpos() function with any other values for pos is undefined behavior 181.
Noncompliant Code Example
This noncompliant code example
| Wiki Markup |
|---|
Calling {{fsetpos()}} sets the file position indicator of a file stream. According to C99 \[[ISO/IEC 9899-1999|AA. C References#ISO/IEC 9899-1999]\], 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|BB. Definitions#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 file position pointer back to the beginning of the file and return to the caller.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> int opener(FILE *file) { int enum { NO_FILE_POS_VALUES = 3 }; errno_t 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-1; } if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES) { return EIO; } if ((/* Read in data from file */ rc = fsetpos(file, &offset)); if (rc != 0 ) { return rc; } *width = file_w; *height = file_h; *data_offset = file_o;return rc; } return 0; } |
However, because only Only the return value of a an fgetpos() call is a valid argument to be used with fsetpos(), passing an ; passing a value of type 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 fileis undefined behavior 181.
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().:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h> #include <string.h> int opener(FILE *file) { int enum { NO_FILE_POS_VALUES = 3 }; errno_t 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; return -1; } if ((rc = fgetpos(file, &offset)); if (rc != 0 ) { return return rc; } if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o) != NO_FILE_POS_VALUES) { return EIO; } if ((/* Read in data from file */ rc = fsetpos(file, &offset)); if (rc != 0 ) { return rc; } *width = return file_wrc; *height = file_h; *data_offset = file_o; } return 0; } |
Risk Assessment
The misuse Misuse of the fsetpos() could move function can position a file stream read to a undesired 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 position indicator to an unintended location in the file.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|---|---|
FIO44-C | Medium |
Unlikely |
No |
No |
P2 | L3 |
Automated Detection
...
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| CodeSonar |
| (customization) | Users can add a custom check for violations of this constraint. | ||||||
| Compass/ROSE | Can detect common violations of this rule. However, it cannot handle cases in which the value returned by | ||||||||
| Cppcheck Premium |
| premium-cert-fio44-c | |||||||
| Helix QAC |
| DF4841, DF4842, DF4843 | |||||||
| Klocwork |
| CERT.FSETPOS.VALUE | |||||||
| LDRA tool suite |
| 82 D | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-FIO44-a | Only use values for fsetpos() that are returned from fgetpos() | ||||||
| Polyspace Bug Finder |
| CERT C: Rule FIO44-C | Checks for invalid file position (rule partially covered) | ||||||
| PVS-Studio |
| V1035 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
...
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| ISO/IEC TS 17961:2013 | Using a value for fsetpos other than a value returned from fgetpos [xfilepos] | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
| [ISO/IEC 9899:2024] | 7.23 |
...
| .9.3, |
...
"The fsetpos Function" |
...
{{fsetpos}} function"FIO43-C. Temporary files must be dealt with in a secure manner 09. Input Output (FIO) 10. Environment (ENV)