2010-06-04 40 views
9

Estoy programando en C en Unix, y estoy usando gets para leer las entradas del teclado. Siempre tengo esta advertencia y el programa para dejar de correr:¿por qué get() no está funcionando?

warning: this program uses gets(), which is unsafe. 

¿Puede alguien decirme la razón de por qué ocurre esto?

+0

Es una función insegura; Se pueden emitir ataques de desbordamiento de búfer si los programas usan funciones que no ofrecen la posibilidad de verificar el tamaño del búfer – INS

+0

Si uso scanf() en lugar de gets() funciona, pero tengo que leer 2 entradas del teclado y el programa se detiene después de leer el primero. ¿Por qué? este es el código: usuario de char; pase de char; printf ("Iser ID"); scanf ("% s", usuario); printf ("Código PIN:"); scanf ("% s", pase); – Peiska

+1

@peiska: el programa se detiene después del primero porque está esperando que ingrese el segundo. Tú mismo pones ese segundo 'scanf' allí. ¿Por qué te sorprende que el programa "pare" entonces? – AnT

Respuesta

8

Como se menciona en las respuestas anteriores, utilice fgets en lugar de gets.

Pero no es como gets no funciona en absoluto, es muy muy inseguro. Supongo que tiene un error en su código que aparecería con fgets, así que publique su fuente.

EDIT Según la información actualizada que ha proporcionado en su comentario, tengo algunas sugerencias.

  • Recomiendo buscar un buen tutorial de C en su lengua materna, Google es su amigo aquí. Como libro, recomendaría The C Programming Language

  • Si tiene nueva información, es una buena idea editarla en su publicación original, especialmente si es un código, hará que sea más fácil para las personas entender lo que usted quiere decir.

  • Está tratando de leer una cadena, básicamente una matriz de caracteres, en un solo carácter, que por supuesto fallará. Lo que quieres hacer es algo como lo siguiente.

    char username[256]; 
    char password[256]; 
    scanf("%s%s", username, password); 
    

    Siéntase libre de comentar/editar, soy muy oxidada incluso en C. básica

EDIT 2 Como jamesdlin advirtió, el uso de scanf es tan peligroso como gets.

+0

Su uso 'scanf' es tan malo como' get'. (Evite usar 'scanf' también: http://c-faq.com/stdio/scanfprobs.html) – jamesdlin

+0

@jamesdlin Gracias por el aviso, no sabía sobre el problema del desbordamiento del búfer, aunque me he encontrado con otros problemas con scanf antes. – ponzao

13

gets no es seguro porque le da un búfer, pero no le dice qué tan grande es el búfer. La entrada puede escribir más allá del final del búfer, explotando su programa de manera espectacular. Usando fgets lugar es un poco mejor, ya que dice que el tamaño del búfer es, de esta manera:

const int bufsize = 4096; /* Or a #define or whatever */ 
char buffer[bufsize]; 

fgets(buffer, bufsize, stdin); 

... así siempre y cuando se da la información correcta, no escribe más allá del final del búfer y explotar las cosas.

Ligeramente OT, pero:

Usted no tiene que utilizar un const int para el tamaño del búfer, pero lo haría fuertemente recomendamos que no sólo hay que poner un número literal en ambos lugares, ya que inevitablemente Cambiará uno pero no el otro más tarde. El compilador puede ayudar:

char buffer[4096]; 
fgets(buffer, (sizeof buffer/sizeof buffer[0]), stdin); 

Esa expresión se resuelve en tiempo de compilación, no en tiempo de ejecución. Es un dolor que escribir, así que solía utilizar una macro en mi juego habitual de los encabezados:

#define ARRAYCOUNT(a) (sizeof a/sizeof a[0]) 

... pero estoy un par de años de retraso con mi C puro, es probable que haya una mejor manera estos días.

+0

si se trata de una matriz de 'char', no hay necesidad de dividir por' sizeof buffer [0] 'como' sizeof (char) == 1' por definición, es decir, la llamada a la función se puede simplificar a 'fgets (buffer, sizeof buffer, stdin) ' – Christoph

+0

@Christoph: ¿Está * seguro * de que' char' será un byte en todas las plataformas, y/o si es (digamos) dos bytes, que el argumento de tamaño buf para 'fgets 'se aplicará como * caracteres * en lugar de * bytes *? La mayoría de los documentos que he visto tienen dichos bytes. He estado fuera del juego C un tiempo y sé que esto se ha vuelto más complicado, así que estaba siendo un poco defensivo en el código. Pero sí, @OP, * si * esas suposiciones son seguras, entonces puede omitir el cálculo con una matriz 'char' (pero no aplicaciones similares de esta expresión idiomática con' int', 'long', etc.). –

+0

@ T.J. Crowder: El estándar C * define * 'char' como 1 byte. – jamesdlin

5

man gets dice:

Nunca use gets(). Debido a que es imposible saber, sin conocer los datos de antemano cuántos caracteres gets() leerá, y debido a gets() continuará almacenando caracteres más allá del final de la memoria intermedia, es extremadamente peligroso para su uso . Se ha utilizado para romper la seguridad de la computadora . Use fgets() en su lugar.

1

gets() no es seguro. Toma un parámetro, un puntero a un búfer char. Pregúntese qué tan grande tiene que hacer ese buffer y cuánto tiempo un usuario puede ingresar datos sin presionar la tecla de retorno.

Básicamente, no hay forma de evitar un desbordamiento del búfer con gets() - use fgets().

Cuestiones relacionadas