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 two mistakes you can make when calling fopen() that fopen_s()
protects against:
FILE *file = fopen(NULL, inmode);
This code has undefined behavior "by the omission of any explicit
definition of behavior" (4p2), since the description of what fopen()
does with its filename argument (7.21.5.3p2) is meaningless when that
argument 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 second 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.
I don't see any value in adding a level of indirection to the mode. All
is does is create new ways for the function to fail: if the third
argument is null, it fails with defined behavior: no attempt will be
made to open the file, and *streamptr will be set to a null pointer
value, and fopen_s(). However, because of the restrict qualifiers, if
the third argument points at memory which overlaps that pointed at by
streamptr, filename, the behavior is undefined; a situation that
couldn't meaningfully be a problem with fopen().