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 position back to the beginning of the file and return to the caller.

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; }
  if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o)  
      != NO_FILE_POS_VALUES) { return EIO; }
  if ((rc = fsetpos(file, &offset)) != 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 valid to be used with 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 };

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; }
  if ((rc = fgetpos(file, &offset)) != 0 ) { return rc; }
  if (fscanf(file, "%u %u %u", &file_w, &file_h, &file_o)  
      != NO_FILE_POS_VALUES) { return EIO; }
  if ((rc = fsetpos(file, &offset)) != 0 ) { return rc; }

  *width = file_w;
  *height = file_h;
  *data_offset = file_o;

  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 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|AA. C References#ISO/IEC 9899-1999]\] Section 7.19.9.3, "The {{fsetpos}} function"


FIO43-C. Temporary files must be dealt with in a secure manner      09. Input Output (FIO)       10. Environment (ENV)