Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Changed compliant solution to use Annex K; noted that MSVC does not support 'x'; added a Windows CS

...

Code Block
bgColor#FFCCCC
langc
char *file_name;
FILE *fp;

/* Initialize file_name */
errno_t res = fopen_s(&fp, file_name, "w");
if (res != 0) {
  /* Handle error */
}

Compliant Solution (fopen_s(), C11 Annex K)

The C Standard provides a new flag to address this problem. Section 7.21.5.3, paragraph 5 [ISO/IEC 9899:2011], states:

...

This compliant solution uses the x mode character to instruct fopen_s() to fail rather than open an existing file:

Code Block
bgColor#ccccff
langc
char *file_name;

/* Initialize file_name */

FILE *fp;
errno_t res = fopen(&fp, file_name, "wx");
if (res !fp= 0) {
  /* Handle error */
}

Use of this option allows for the easy remediation of legacy code.  However, note that Microsoft Visual Studio 2012 and earlier do not support the 'x' mode character [MSDN].

Compliant Solution (open(), POSIX)

...

Code Block
bgColor#ccccff
langc
char *file_name;
int new_file_mode;
FILE *fp;
int fd;

/* Initialize file_name and new_file_mode */

fd = open(file_name, O_CREAT | O_EXCL | O_WRONLY, new_file_mode);
if (fd == -1) {
  /* Handle error */
}

fp = fdopen(fd, "w");
if (fp == NULL) {
  /* Handle error */
}

Compliant Solution (Windows)

The Win32 API CreateFile() allows you to create or open a file depending on the flags passed in.  By passing in the CREATE_NEW flag, you can ensure the call fails if the file already exists.  This compliant solution demonstrates how to open a file for reading and writing, without sharing access to the file such that the call fails if the file already exists.

Code Block
bgColor#ccccff
langc
TCHAR *file_name;
HANDLE hFile = CreateFile(file_name, GENERIC_READ | GENERIC_WRITE, 0, 0, 
                          CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
if (INVALID_HANDLE_VALUE == hFile) {
  DWORD err = GetLastError();
  if (ERROR_FILE_EXISTS == err) {
    /* Handle file exists error */
  } else {
    /* Handle other error */
  }
}

Risk Assessment

The ability to determine if an existing file has been opened or a new file has been created provides greater assurance that a file other than the intended file is not acted upon.

...