Я работаю над устаревшим кодом для Windows
Платформа. Когда я компилирую код в VS2013
Дайте следующее предупреждение:
ошибка C4996: ‘
fopen
‘: Эта функция или переменная может быть небезопасной. Рассмотреть возможность использованияfopen_s
вместо. Чтобы отключить устаревание, используйте _CRT_SECURE_NO_WARNINGS. Смотрите справку для деталей.»
И это также даст знакомое предупреждение для sprintf
, я понимаю sprintf_s
более безопасен, чем sprintf из-за переполнения буфера.
Но как можно fopen_s быть более безопасным, чем fopen
, нет никаких шансов переполнения буфера, потому что fopen
не принимает буфер Может ли кто-нибудь представить случай fopen
небезопасно, и fopen_s
безопасно?
s
в данном случае не означает «безопасный», он означает «повышенная безопасность». За fopen_s
параметры проверяются на достоверность перед попыткой открыть файл.
С fopen
, вы можете передать NULL указатель на имя файла, и все, скорее всего, распадется на части. fopen_s
не имеет этой проблемы (А).
Имейте в виду, что эти границы проверки интерфейсов, таких как fopen_s
являются необязательный часть стандарта ИСО, подробно изложенная в Приложении K (во всяком случае, на C11). Реализации не требуется обеспечить их и, если честно, fopen
и многие другие так называемые небезопасные функции совершенно безопасны, если вы знаете, что делаете как кодировщик.
Интересно отметить, что fopen_s
будет ловить указатели NULL для вас, но не для недействительных указателей, поэтому его безопасность повышена, а не безопасна — вы все равно можете нанести некоторый ущерб, если передадите недействительный, но ненулевой указатель.
Другие «безопасные» функции, которые вынуждают вас предоставлять размер буфера назначения, также безопасны, только если вы передаете правильный размер. Передайте что-то слишком большое, и все ставки сняты.
(А) От 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);
Время воспроизведения-ограничение
Ни один из streamptr, filename или mode не должен быть нулевым указателем.
Если есть нарушение ограничения времени выполнения, fopen_s не пытается открыть файл. Кроме того, если streamptr не является нулевым указателем, fopen_s устанавливает * streamptr в нулевой указатель.
Сравните это с C11 7.20.5.3 The fopen function
в котором говорится, что имя файла и режим должны указывать на строку, но не указывают, что произойдет, если вы укажете NULL-указатель (большинство реализаций, скорее всего, завершится с ошибкой разыменования нулевого указателя).
Других решений пока нет …