c++ - _crt_secure_no_warnings - fopen fopen_s
¿Cómo pueden los fopen_s ser más seguros que los fopen? (1)
Estoy trabajando en el código heredado para la plataforma Windows
. Cuando compilo el código en VS2013
, da la siguiente advertencia:
error C4996: ''
fopen
'': esta función o variable puede no ser segura. Considera usarfopen_s
enfopen_s
lugar. Para deshabilitar la desaprobación, utilice _CRT_SECURE_NO_WARNINGS. Consulte la ayuda en línea para obtener detalles."
Y también dará una advertencia familiar para el sprintf
. Entiendo que sprintf_s
es más seguro que sprintf debido al desbordamiento del búfer.
Pero, ¿cómo puede ser fopen_s más seguro que fopen
No hay posibilidad de desbordamiento de búfer porque fopen
no acepta un búfer. ¿Alguien puede proporcionar un caso que fopen
no es seguro y que fopen_s
es seguro?
La s
no significa "seguro" en este caso, significa "seguridad mejorada". Para fopen_s
, se comprueba la validez de los parámetros antes de intentar abrir el archivo.
Con fopen
, puedes pasar un puntero NULO para el nombre del archivo y es probable que todo se caiga a pedazos. fopen_s
no tiene ese problema (a) .
Tenga en cuenta que estas interfaces de verificación de límites como fopen_s
son una parte opcional de la norma ISO, que se detalla en el Anexo K (como en C11, de todos modos). No es necesario que las implementaciones las proporcionen y, para ser honesto, fopen
, y muchas otras funciones llamadas inseguras, son perfectamente seguras si sabes lo que estás haciendo como programador.
Es interesante observar que fopen_s
atrapará los punteros NULL para usted pero no los punteros no válidos, por lo tanto, la seguridad mejorada en lugar de segura: aún puede causar algún daño si pasa un puntero no válido pero no NULL.
Otras funciones "seguras" que lo obligan a proporcionar tamaños de búfer de destino también son seguras siempre que pase el tamaño correcto. Pasa algo demasiado grande y todas las apuestas están apagadas.
(a) De 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);
Restricciones de tiempo de ejecución
Ninguno de streamptr, filename o mode será un puntero nulo.
Si hay una violación de restricción de tiempo de ejecución, fopen_s no intenta abrir un archivo. Además, si streamptr no es un puntero nulo, fopen_s establece * streamptr en el puntero nulo.
Contraste que con C11 7.20.5.3 The fopen function
que indica que el nombre de archivo y el modo deben apuntar a una cadena pero no especificar qué sucede si proporciona un puntero NULO (la mayoría de las implementaciones probablemente se bloquearían con una desreferencia de puntero nulo).