Pregunta

De man gets:

Nunca use Gets (). Debido a que es imposible saberlo sin conocer los datos de antemano cuántos caracteres se leerán (), y porque Gets () continuará almacenando personajes más allá del final del búfer, es extremadamente peligroso de usar. Se ha utilizado para romper la seguridad informática. Use fgets () en su lugar.

Casi donde sea que veo scanf ser utilizado de una manera que debería tener el mismo problema (desbordamiento del búfer/búfer desbordado): scanf("%s",string). ¿Este problema existe en este caso? Por qué no hay referencias al respecto en el scanf Página del hombre? Por qué GCC no advierte al compilar esto con -Wall?

PD: Sé que hay una manera de especificar en la cadena de formato la longitud máxima de la cadena con scanf:

char str[10];
scanf("%9s",str);

Editar: no estoy pidiendo determinar si el código anterior es correcto o no. Mi pregunta es: si scanf("%s",string) ¿Siempre está mal, por qué no hay advertencias y no hay nada al respecto en la página del hombre?

¿Fue útil?

Solución

La respuesta es simplemente que nadie ha escrito el código en GCC para producir esa advertencia.

Como señala, una advertencia para el caso específico de "%s" (sin ancho de campo) es bastante apropiado.

Sin embargo, tenga en cuenta que este es solo el caso del caso de scanf(), vscanf(), fscanf() y vfscanf(). Este especificador de formato puede ser perfectamente seguro con sscanf() y vsscanf(), por lo que la advertencia no debe emitirse en ese caso. Esto significa que no puede simplemente agregarlo al código de análisis existente de "Tanf-Style-Format-String"; Tendrá que dividir eso en las opciones de "cadena de formato de estilo FSCANF" y "SSCANF-Style-Format-String".

Estoy seguro de que si produce un parche para la última versión de GCC, tiene una buena posibilidad de ser aceptado (y, por supuesto, también deberá enviar parches para los archivos de encabezado GLIBC).

Otros consejos

Usando gets() nunca es seguro. scanf() Se puede usar de manera segura, como dijo en su pregunta. Sin embargo, determinar si lo está utilizando de manera segura es un problema más difícil para el compilador. scanf() En una función en la que pasa en el búfer y un personaje cuenta como argumentos, no podrá decirlo); En ese caso, tiene que asumir que sabes lo que estás haciendo.

Cuando el compilador mira la cadena de formato de scanf, ve una cuerda! Eso supone que la cadena de formato no se ingresa en el tiempo de ejecución. Algunos compiladores como GCC tienen una funcionalidad adicional para analizar la cadena de formato si se ingresa en el momento de la compilación. Esa funcionalidad adicional no es completa, porque en algunas situaciones se necesita una sobrecarga en el tiempo de ejecución, que es un NO para idiomas como C. Por ejemplo, ¿puede detectar un uso inseguro sin insertar algún código oculto adicional en este caso:

char* str;
size_t size;
scanf("%z", &size);
str = malloc(size);
scanf("%9s"); // how can the compiler determine if this is a safe call?!

Por supuesto, hay formas de escribir código seguro con scanf Si especifica el número de caracteres para leer, y que hay suficiente memoria para mantener la cadena. En el caso de gets, no hay forma de especificar el número de caracteres para leer.

No estoy seguro de por qué la página del hombre para SCANF no menciona la probabilidad de un búfer desbordado, pero Vanilla Scanf no es una opción segura. Un enlace bastante anticuado - http://blogs.msdn.com/b/rsamona/archive/2005/10/24/484449.aspx muestra esto como el caso. Además, verifique esto (no GCC sino informativo, sin embargo) - http://blogs.msdn.com/b/parthas/archive/2006/12/06/application-crash-on-replacing-scanf-withsscanf-s.aspx

Puede ser simplemente que ScanF asignará espacio en el montón en función de la cantidad de datos. Dado que no asigna el búfer y luego lee hasta que se lea el carácter nulo, no corre el riesgo de sobrescribir el búfer. En cambio, se lee en su propio búfer hasta que se encuentra el carácter nulo, y presumiblemente copia ese amortiguador en otro de tamaño correcto al final de la lectura.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top