Why is function fopen deprecated in MSVC from MSVC2005?

240 views Asked by At

In ISO C, function fopen is used to open a file.

FILE *fp = fopen ("text.txt", "r");

But from MSVC2005, Microsoft mark this function deprecated. An MSVC-specific function fopen_s created by Microsoft is recommended in 2005 or higher version of MSVC.

FILE *fp = NULL;
fopen_s (&fp, "text.txt", "r");

The main difference between these two functions is the return value type. ISO C function fopen returns a pointer to the new file stream if success, NULL if fail. However, the return value type of MSVC function fopen_s is int, which returns zero if success, non-zero integer if fail.

The question is: Why Microsoft mark the standard function fopen returning FILE * deprecated, recommending its own function fopen_s returning int from MSVC2005? (This question is about the reason why Microsoft does this, not how to disable the deprecation)

1

There are 1 answers

9
Lundin On

Why is function fopen deprecated in MSVC from MSVC2005?

Because Microsoft did some big analysis at the time regarding which functions that were often exploited or present in buggy programs. Then they did the wrong conclusion that those functions were the culprit and not the incompetent programmer who had written a program full of exploits and bugs. So they decided to get rid of the symptoms not the root cause by flagging various perfectly fine functions as obsolete.

It's fairly impossible to exploit fopen unless you pass unsanitized user input to it directly as parameter. Which is not fault of this function, the cause of that problem is the uneducated quack programmer who did such a stupid thing.

Rather than blacklisting a bunch of mostly fine functions, it would have been more meaningful to start educating programmers regarding how they should sanitize input, by using fgets, memchr and other such functions.

So mostly Microsoft were being confused, although in their defence, they did also start to perfectly sensibly warn against using some broken-by-design functions such as gets and strncpy.


The main difference between these two functions is the return value type. ISO C function fopen returns a pointer to the new file stream if success, NULL if fail. However, the return value type of MSVC function fopen_s is int, which returns zero if success, non-zero integer if fail.

It would seem that the main difference is that the old, non-standard fopen_s returns an error upon receiving a null pointer parameter, which is an error check of very dubious value.

As far as I can tell, Microsoft's version is not compatible with the C11 bounds-checking interface with the same function present. The bounds-checking fopen_s comes with an 'u' suffix option to the mode parameter, which I can't find mentioned in Microsoft's documentation.

Well, lets try if MSVC even implements the bounds-checking interface from C11, it's easy to do:

#ifndef __STDC_LIB_EXT1__
  #error This compiler does not support fopen_s.
#endif

Result on the latest and greatest MSVC 19.32 from 2022 (compile with /std:c17):

fatal error C1189: #error: This compiler does not support fopen_s.

Hmm well that's probably for the best anyway since the bounds-checking interface has been heavily criticised, see for example this excellent paper Field Experience With Annex K — Bounds Checking Interfaces

But well, just to be clear, lets see if we accidentally picked a non-C compiler by testing for compliance with ISO/IEC 9899:1990/AMD1:1995 or better:

#ifndef __STDC__
  #error This compiler was deprecated in 1995. Consider using gcc instead.
#endif

Result on the latest and greatest MSVC 19.32 from 2022 (compile with /std:c17):

fatal error C1189: #error: This compiler was deprecated in 1995. Consider using gcc instead.

Oh dear. I better start looking for a C compiler from 1996 or later.