I'm working on legacy code for Windows
platform. When I compile the code in VS2013
, it give following warning:
error C4996: '
fopen
': This function or variable may be unsafe. Consider usingfopen_s
instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."
And it will also give samiliar warning for sprintf
. I understand sprintf_s
is more safe than sprintf because of buffer overflow.
But how can be fopen_s be more safe than fopen
, there is no chance of buffer overflow because fopen
doesn't accept an buffer. Can anyone provide an case fopen
is unsafe, and fopen_s
is safe?
The s
doesn't stand for "safe" in this case, it stands for "security enhanced". For fopen_s
, the parameters are checked for validity before attempting to open the file.
With fopen
, you can pass a NULL pointer for the filename and everything will most likely fall to pieces. fopen_s
doesn't have that problem (a).
Keep in mind that these bounds checking interfaces like fopen_s
are an optional part of the ISO standard, detailed in Annex K (as at C11, anyway). Implementations are not required to provide them and, to be honest, fopen
, and many other so-called unsafe functions, are perfectly safe if you know what you're doing as a coder.
It's interesting to note that fopen_s
will trap NULL pointers for you but not invalid pointers, hence why it's security enhanced rather than safe - you can still cause some damage if you pass an invalid but non-NULL pointer.
Other "safe" functions which force you to provide destination buffer sizes are also safe only as long as you pass the right size. Pass something too big and all bets are off.
(a) From C11 K.3.5.2.1 The fopen_s function
:
errno_t fopen_s (
FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
Runtime-constraints
None of streamptr, filename, or mode shall be a null pointer.
If there is a runtime-constraint violation, fopen_s does not attempt to open a file. Furthermore, if streamptr is not a null pointer, fopen_s sets *streamptr to the null pointer.
Contrast that with C11 7.20.5.3 The fopen function
which states that the filename and mode must both point to a string but don't specify what happens if you provide a NULL pointer (most implementations would likely crash with a null pointer dereference).