J
James Kuyper
Several parts of my previous message (which I just cancelled, but you
may still be able to see it) made no sense due to a stupid thinking
error about the mode argument of fopen(). Please ignore that version, in
favor of this one:
I think, at least in this case, that it's more about safety than about
security.
Here's the declaration for fopen():
FILE *fopen(const char * restrict filename,
const char * restrict mode);
Here's the declaration for fopen_s():
errno_t fopen_s(FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
There are three mistakes you can make when calling fopen() that
fopen_s() protects against:
FILE *infile = fopen(NULL, inmode);
FILE *outfile = fopen(outfilename, NULL);
These calls have undefined behavior "by the omission of any explicit
definition of behavior" (4p2), since the description of what fopen()
does with its filename and mode arguments (7.21.5.3p2) is meaningless
when either of those arguments is a null pointer. The corresponding code
using fopen_s() has defined behavior: it will make no attempt to open a
file, *streamptr will be set to a null pointer value (K.3.5.2.1p2,3),
and fopen_s() will return a non-zero value. This strikes me as a good idea.
The third mistake would be something like the following:
fopen(outfilename, outmode);
This code opens a file without having any way to do anything with it,
including close it. The corresponding code using fopen_s() would be:
FILE *outfile;
fopen_s(&outfile, outfilename, outmode);
You can still discard outfile immediately, producing the same net
result, but the necessity of creating a valid pointer to a FILE* object
makes it harder to make that particular error accidentally.
may still be able to see it) made no sense due to a stupid thinking
error about the mode argument of fopen(). Please ignore that version, in
favor of this one:
Am 10.05.2013 16:32, schrieb James Kuyper:
Sorry for getting off-topic, but could anyone explain me what on fopen()
might be insecure? ...
I think, at least in this case, that it's more about safety than about
security.
...It does not write to its arguments, expects just
const strings as arguments it has to parse, so how could one use fopen
in a way that breaches security that is not available with fopen_s()?
Ok, shoot yourself in the foot by potentially writing to files you want
to (or need to) keep, but that's not different from fopen_s(), is it?
Here's the declaration for fopen():
FILE *fopen(const char * restrict filename,
const char * restrict mode);
Here's the declaration for fopen_s():
errno_t fopen_s(FILE * restrict * restrict streamptr,
const char * restrict filename,
const char * restrict mode);
There are three mistakes you can make when calling fopen() that
fopen_s() protects against:
FILE *infile = fopen(NULL, inmode);
FILE *outfile = fopen(outfilename, NULL);
These calls have undefined behavior "by the omission of any explicit
definition of behavior" (4p2), since the description of what fopen()
does with its filename and mode arguments (7.21.5.3p2) is meaningless
when either of those arguments is a null pointer. The corresponding code
using fopen_s() has defined behavior: it will make no attempt to open a
file, *streamptr will be set to a null pointer value (K.3.5.2.1p2,3),
and fopen_s() will return a non-zero value. This strikes me as a good idea.
The third mistake would be something like the following:
fopen(outfilename, outmode);
This code opens a file without having any way to do anything with it,
including close it. The corresponding code using fopen_s() would be:
FILE *outfile;
fopen_s(&outfile, outfilename, outmode);
You can still discard outfile immediately, producing the same net
result, but the necessity of creating a valid pointer to a FILE* object
makes it harder to make that particular error accidentally.