¿Por qué gets() no funciona?

6 minutos de lectura

¿Por que gets no funciona
Peiska

Estoy programando en C en Unix, y estoy usando gets para leer las entradas del teclado. Siempre recibo esta advertencia y el programa deja de ejecutarse:

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

¿Alguien puede decirme la razón por la que esto está sucediendo?

  • 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.

    – EN S

    4 de junio de 2010 a las 12:44

  • Si uso scanf() en lugar de gets(), funciona, pero tengo que leer 2 entradas desde el teclado y el programa se detiene después de leer la primera. ¿Por qué? este es el codigo: char usuario; pase de char; printf(“Iser ID”); scanf(“%s”,usuario); printf(“Código pin:”); escanear(“%s”,pasar);

    – Peiska

    4 de junio de 2010 a las 12:59

  • @peiska: El programa se detiene después del primero porque está esperando que ingreses al segundo. Tu mismo pones ese segundo scanf ahí. ¿Por qué te sorprende que el programa “se detenga” entonces?

    – Ant

    4 de junio de 2010 a las 15:23

  • user y pass necesita ser declarado como arreglos de caracteres, no de caracteres individuales. El especificador de conversión “%s” espera que el argumento correspondiente tenga el tipo char *y ese argumento debe apuntar a un búfer que sea lo suficientemente largo para contener la cadena de entrada más el terminador 0 (el especificador de conversión “%s” sin decorar expone la misma falla de seguridad que gets() en ese sentido, pero no hay suficiente espacio aquí para entrar en eso en detalle). Cambiar las declaraciones de user y pass para char user[N]; char pass[M] donde N y M son los tamaños que necesita para las dos matrices.

    – Juan Bode

    4 de junio de 2010 a las 16:03

¿Por que gets no funciona
TJ Crowder

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 bastante espectacular. Utilizando fgets en cambio, es un poco mejor porque le dices qué tan grande es el búfer, así:

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

fgets(buffer, bufsize, stdin);

… así que siempre que le proporcione la información correcta, no escribe más allá del final del búfer y explota las cosas.

Ligeramente OT, pero:

No tienes que usar un const int para el tamaño del búfer, pero lo haría fuertemente Le recomendamos que no ponga un número literal en ambos lugares, porque inevitablemente cambiará uno pero no el otro más adelante. 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 una molestia escribir, así que solía usar una macro en mi conjunto habitual de encabezados:

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

…pero tengo algunos años desactualizados con mi C puro, probablemente haya una mejor manera en estos días.

  • si se trata de una serie de charno 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)

    – Cristóbal

    4 de junio de 2010 a las 14:20

  • @Christoph: ¿Estás cierto que char será de un byte en todas las plataformas, y/o si son (digamos) dos bytes, el argumento tamaño buf para fgets se aplicará como caracteres en vez de bytes ? La mayoría de los documentos que he visto han dicho bytes. He estado fuera del juego C por un tiempo y sé que esto se ha vuelto más complicado, así que estaba un poco a la defensiva en el código. Pero sí, @OP, si esas suposiciones son seguras, entonces puede omitir el cálculo con un char matriz (pero no aplicaciones similares de este modismo con int, longetc).

    –TJ Crowder

    4 de junio de 2010 a las 16:24


  • @TJ Crowder: El estándar C define char ser de 1 byte.

    – jamesdlin

    4 de junio de 2010 a las 18:12

  • @TJ Crowder: consulte C99 sección 3.7.1 que establece que los caracteres C son de un solo byte y 6.5.3.4 §3, que menciona explícitamente que sizeof (char) siempre es 1

    – Cristóbal

    4 de junio de 2010 a las 18:42

  • Es C. no C++, así que usa #define o enum.

    – Nyan

    5 de junio de 2010 a las 9:09

1647676870 225 ¿Por que gets no funciona
ponzao

Como se mencionó en las respuestas anteriores, use fgets en lugar de gets.

pero no es como gets no funciona en absoluto, es muy, muy inseguro. Supongo que tienes un error en tu código que aparecería con fgets así que por favor publique su fuente.

EDITAR
Según la información actualizada que proporcionó en su comentario, tengo algunas sugerencias.

  • Recomiendo buscar un buen tutorial de C en su idioma nativo, Google es su amigo aquí. como libro lo recomiendo El lenguaje de programación C

  • Si tiene información nueva, 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 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, estoy muy oxidado incluso en C básico.

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

  • Tu scanf el uso es tan malo como gets. (Evitar el uso de scanf también: c-faq.com/stdio/scanfprobs.html )

    – jamesdlin

    4 de junio de 2010 a las 18:14

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

    – ponzao

    04/06/2010 a las 21:30

man gets dice:

Nunca use gets(). Debido a que es imposible saber sin conocer los datos de antemano cuántos caracteres leerá get(), y debido a que gets() continuará almacenando caracteres más allá del final del búfer, es extremadamente peligroso usarlo. Se ha utilizado para romper la seguridad informática. Utilice fgets() en su lugar.

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

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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad