Section 7.21.9.3 of the C standard [ISO/IEC 9899:2011] defines the following behavior for fsetpos():

The fsetpos function sets the mbstate_t object (if any) and file position indicator for the stream pointed to by stream according to the value of the object pointed to by pos, which shall be a value obtained from an earlier successful call to the fgetpos function on a stream associated with the same file.

Consequently, using any other values for pos results in undefined behavior and should be avoided.

Noncompliant Code Example

This noncompliant code example 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, /* ... */ ) {
  int rc;
  fpos_t offset;

  /* ... */

  memset(&offset, 0, sizeof(offset));

  if (file == NULL) { return EINVAL; }

  /* Read in data from file */

  rc = fsetpos(file, &offset);
  if (rc != 0 ) { return rc; }

  /* ... */

  return 0;
}

However, because only the return value of an 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, /* ... */) {
  int rc;
  fpos_t offset;

  /* ... */

  if (file == NULL) { return EINVAL; }

  rc = fgetpos(file, &offset);
  if (rc != 0 ) { return rc; }

  /* Read in data from file */

  rc = fsetpos(file, &offset);
  if (rc != 0 ) { return rc; }

  /* ... */

  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

Tool

Version

Checker

Description

Fortify SCA

V. 5.0

 

Can detect violations of this rule with CERT C Rule Pack.

Compass/ROSE

 

 

Can detect common violations of this rule. However, it cannot handle cases in which the value returned by fgetpos() is copied between several variables before being passed to fsetpos().

LDRA tool suite

82 D

Fully implemented.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

CERT C++ Secure Coding Standard: FIO44-CPP. Only use values for fsetpos() that are returned from fgetpos()

ISO/IEC 9899:2011 Section 7.21.9.3, "The fsetpos function"

ISO/IEC TR 17961 (Draft) Using a value for fsetpos other than a value returned from fgetpos [xfilepos]

Bibliography